JavaScript 의 this 바 인 딩 에 대해 자세히 설명 합 니 다.

11107 단어
this 는 자바 script 에서 가장 흥미 로 운 특성 이 라 고 할 수 있 습 니 다. 마치 고등학교 영어 에서 여러 가지 시제, 예 를 들 어 수 동적 시제, 과거, 현재, 과거 진행 시 처럼 몇 번 을 놓 치 더 라 도 다음 에는 틀 릴 수 있 습 니 다.본 고 는 《 당신 이 모 르 는 자 바스 크 립 트 상권 》 을 계발 하여 자 바스 리 프 트 중의 this 를 총 결 하 였 다.
this 를 배 우 는 첫 번 째 단 계 는 this 가 함수 자체 도 가리 키 지 않 고 함수 의 역할 영역 도 가리 키 지 않 는 다 는 것 을 깨 닫 는 것 이다.this 는 실제 함수 가 호출 될 때 발생 하 는 바 인 딩 입 니 다. 이 는 함수 가 어디에서 호출 되 는 지 에 달 려 있 습 니 다.
기본 바 인 딩
javascript 에서 가장 많이 사용 되 는 함수 호출 유형 은 독립 함수 호출 이기 때문에 이 규칙 을 다른 규칙 을 적용 할 수 없 을 때의 기본 규칙 으로 볼 수 있 습 니 다.만약 에 함 수 를 호출 할 때 함수 가 어떠한 수식 도 가지 고 있 지 않 습 니 다. 즉, '대머리' 의 호출 이 라면 기본 바 인 딩 규칙 을 사용 하고 기본 바 인 딩 은 전체 역할 영역 을 가리 키 는 것 입 니 다.

function sayLocation() {
 console.log(this.atWhere)
}

var atWhere = "I am in global"

sayLocation() //     ,this       ,   “I am in global”



예 를 하나 더 보다.

var name = "global"
function person() {
 console.log(this.name) // (1) "global"
  person.name = 'inside'
 function sayName() {
  console.log(this.name) // (2) "global"    "inside"
 }
 sayName() //  person      sayName  ,this           
}
person()

이 예 에서 person 함 수 는 전역 작용 역 에서 호출 되 기 때문에 (1) 구 의 this 는 전역 대상 에 연결 되 어 있 습 니 다. (브 라 우 저 에 서 는 window 이 고, node 에 서 는 global 입 니 다.) 따라서 제 (1) 구 는 전역 대상 의 name 속성 을 자 연 스 럽 게 출력 합 니 다. 물론 "global" 입 니 다.sayName 함 수 는 person 함수 에서 호출 됩 니 다. 그럼 에 도 불구 하고 (2) 문장의 this 가 가리 키 는 것 은 전역 대상 입 니 다. person 함수 가 name 속성 을 설정 하 더 라 도.
이것 은 기본 바 인 딩 규칙 입 니 다. 이것 은 자바 script 에서 가장 흔히 볼 수 있 는 함수 호출 모델 입 니 다. this 의 바 인 딩 규칙 도 네 가지 바 인 딩 규칙 중에서 가장 간단 한 것 입 니 다. 바로 전체 역할 영역 에 바 인 딩 하 는 것 입 니 다.
기본 바 인 딩 의 엄격 한 모드
javascript 에서 엄격 한 모드 를 사용 하면 this 는 전역 대상 에 연결 할 수 없습니다.역시 첫 번 째 예 로, 단지 이번에 엄격 한 모델 성명 을 더 했 을 뿐이다.

'use strict'
function sayLocation() {
 console.log(this.atWhere)
}
var atWhere = "I am in global"
sayLocation()
// Uncaught TypeError: Cannot read property 'atWhere' of undefined

이 를 통 해 알 수 있 듯 이 엄격 한 모드 에서 this 를 전체 대상 에 연결 할 때 실제 적 으로 undefined 로 연결 되 어 있 기 때문에 위의 코드 가 잘못 되 었 습 니 다.
암시 적 바 인 딩
함수 가 호출 될 때 함수 에 이른바 '착안점' 이 있 으 면 문맥 대상 이 있 을 때 암시 적 바 인 딩 규칙 은 함수 중의 this 를 이 문맥 대상 에 연결 합 니 다.위의 이 말 이 솔직 하지 않다 고 생각한다 면 코드 를 보 세 요.

function say() {
 console.log(this.name)
}
var obj1 = {
 name: "zxt",
 say: say
}

var obj2 = {
 name: "zxt1",
 say: say
}
obj1.say() // zxt
obj2.say() // zxt1


간단 하 죠?위의 코드 에서 obj 1, obj 2 는 이른바 say 함수 의 착안점 입 니 다. 전문 적 인 표현 은 문맥 대상 입 니 다. 함수 에 이 문맥 대상 을 지정 할 때 함수 내부 의 this 는 자 연 스 럽 게 이 문맥 대상 을 가리 키 고 있 습 니 다.이것 도 흔히 볼 수 있 는 함수 호출 모델 이다.
스텔스 귀속 시 상하 문 분실

function say() {
 console.log(this.name)
}
var name = "global"
var obj = {
 name: "inside",
 say: say
}
var alias = obj.say //        (1) 
alias() //        "global" (2)

여기 서 출력 된 것 은 "global" 입 니 다. 왜 상례 와 다 릅 니까? 우 리 는 분명히 obj. say 에 이름 만 바 꿨 을 뿐 입 니 다. 우선 위 (1) 문장 코드 를 살 펴 보 겠 습 니 다. 자바 script 에서 함 수 는 대상 이 고 대상 간 에는 값 전달 이 아니 라 인용 전달 이기 때 문 입 니 다. 따라서 제 (1)문장 코드 는 alias = obj. say = say, 즉 alias = say, obj. say 는 하나의 다리 역할 을 했 을 뿐 이 며, alias 는 최종 적 으로 say 함수 의 주 소 를 인용 하 였 으 며, obj 라 는 대상 과 는 무관 하 다. 이것 이 바로 '상하 문 분실' 이다. 최종 적 으로 alias 함 수 를 실행 하 였 으 며, say 함 수 를 간단하게 실행 하여 'global' 을 출력 하 였 다.
명시 적 바 인 딩
명시 적 바 인 딩, 말 그대로 this 를 하나의 컨 텍스트 에 표시 합 니 다. 자바 script 에서 세 가지 명시 적 바 인 딩 방법 을 제공 합 니 다. apply, call, bid. apply 와 call 의 용법 은 기본적으로 비슷 합 니 다. 이들 의 차 이 는:
apply (obj, [arg 1, arg 2, arg 3,...] 호출 된 함수 의 매개 변 수 는 배열 형식 으로 call (obj, arg 1, arg 2, arg 3,...) 호출 된 함수 의 매개 변 수 를 순서대로 제시 하고 bid 함수 가 실 행 된 후에 돌아 오 는 것 은 새로운 함수 입 니 다. 다음은 코드 로 설명 합 니 다.

//     
function speak() {
  console.log(this.name)
}

var name = "global"
var obj1 = {
  name: 'obj1'
}
var obj2 = {
  name: 'obj2'
}

speak() // global    speak.call(window)
speak.call(window)

speak.call(obj1) // obj1
speak.call(obj2) // obj2


따라서 apply, call 의 역할 은 함수 에 실행 컨 텍스트 를 연결 하고 명시 적 으로 연결 하 는 것 임 을 알 수 있 습 니 다. 따라서 함수 내 this 는 자 연 스 럽 게 call 또는 apply 가 호출 하 는 대상 에 연결 되 어 있 습 니 다.

//    
function count(num1, num2) {
  console.log(this.a * num1 + num2)
}

var obj1 = {
  a: 2
}
var obj2 = {
  a: 3
}

count.call(obj1, 1, 2) // 4
count.apply(obj1, [1, 2]) // 4

count.call(obj2, 1, 2) // 5
count.apply(obj2, [1, 2]) // 5


위의 이 예 는 apply 와 call 용법 의 차 이 를 설명 합 니 다. bind 함 수 는 지정 한 실행 컨 텍스트 를 연결 한 새로운 함 수 를 되 돌려 줍 니 다. 아니면 위의 코드 를 예 로 들 면 됩 니까?

//    
function count(num1, num2) {
  console.log(this.a * num1 + num2)
}

var obj1 = {
  a: 2
}

var bound1 = count.bind(obj1) //      
bound1(1, 2) // 4

var bound2 = count.bind(obj1, 1) //        
bound2(2) // 4

var bound3 = count.bind(obj1, 1, 2) //        
bound3() //4

var bound4 = count.bind(obj1, 1, 2, 3) //         ,         
bound4() // 4


따라서 bid 방법 은 새로운 함수 만 되 돌려 주 었 습 니 다. 이 함수 안의 this 는 실행 컨 텍스트 를 지정 하고 이 새 함수 로 돌아 가면 인 자 를 받 아들 일 수 있 습 니 다.
새 바 인 딩
마지막 으로 말 할 this 바 인 딩 규칙 은 new 연산 자 를 통 해 구조 함 수 를 호출 할 때 발생 하 는 this 바 인 딩 을 말 합 니 다. 우선 자바 script 에 서 는 다른 언어 와 같은 개념 이 없습니다. 구조 함수 도 일반적인 함수 일 뿐 구조 함수 의 함수 이름 은 대문자 로 시작 할 뿐 new 작업 을 통 해 시작 할 수 있 습 니 다.부적 호출 일 뿐 입 니 다.

function Person(name,age) {
  this.name = name
  this.age = age
  console.log("           ")
}
Person("zxt",22) // "           "
console.log(name) // "zxt"
console.log(age) // 22

var zxt = new Person("zxt",22) // "           "
console.log(zxt.name) // "zxt"
console.log(zxt.age) // 22


위의 예 에서 Person 함 수 를 먼저 정의 합 니 다. 일반 호출 도 가능 하고 구조 함수 로 호출 도 가능 합 니 다. 일반 호출 시 정상 적 인 함수 에 따라 문자열 을 출력 합 니 다. new 연산 자 를 통 해 새로운 대상 을 만 들 었 다 면 두 가지 호출 방식 을 살 펴 보 겠 습 니 다. this 는 각각 연결 되 어 있 습 니 다.우선 일반 호출 이 어디 에 있 는 지 앞에서 소 개 했 습 니 다. 이 때 는 기본 바 인 딩 규칙 을 적용 합 니 다. this 는 전체 대상 에 바 인 딩 되 어 있 습 니 다. 이 때 는 전체 대상 에 각각 name 과 age 두 속성 이 추 가 됩 니 다. new 연산 자 를 통 해 호출 될 때 함 수 는 하나의 대상 으로 돌아 갑 니 다. 출력 결과 에서 볼 때 this 대상 은 이 되 돌아 오 는 대상 에 바 인 딩 되 어 있 습 니 다. 따라서 이른바new 바 인 딩 이란 new 연산 자 를 통 해 함 수 를 호출 할 때 새로운 대상 이 생 성 되 고 구조 함수 에 있 는 this 를 이 대상 에 연결 하 는 것 을 말 합 니 다. 사실 자바 script 에 서 는 new 를 사용 하여 함 수 를 호출 하면 아래 작업 이 자동 으로 실 행 됩 니 다.
  • 새로운 대상 만 들 기
  • 이 새 대상 은 원형 연결 이 실 행 됩 니 다
  • 이 새 대상 은 함수 호출 this
  • 에 연 결 됩 니 다.
  • 함수 가 다른 대상 으로 돌아 가지 않 으 면 new 표현 식 의 함수 호출 은 자동 으로 이 새 대상 으로 돌아 갑 니 다
  • 네 가지 귀속 우선 순위
    자 바스 크 립 트 에 있 는 네 가지 this 귀속 규칙 을 설명 합 니 다. 이 네 가지 귀속 규칙 은 기본적으로 모든 함수 호출 상황 을 포함 합 니 다. 그러나 이 네 가지 규칙 중 두 가지 심지어 더 많은 것 을 동시에 적용 하면 어떤 상황 이 어야 하 는 지, 또는 이 네 가지 귀속 의 우선 순위 가 어떤 지 쉽게 이해 할 수 있 습 니 다. 우선, 기본 귀속 의 우선 순위 가 가장 낮 습 니 다.예. 이것 은 다른 this 바 인 딩 규칙 을 적용 할 수 없 는 상황 에서 만 기본 바 인 딩 을 호출 할 수 있 기 때 문 입 니 다. 암시 적 바 인 딩 과 명시 적 바 인 딩 은 요? 코드 를 올 리 는 것 이 좋 습 니 다. 코드 는 거짓말 을 하지 않 습 니 다.
    
    function speak() {
      console.log(this.name)
    }
    
    var obj1 = {
      name: 'obj1',
      speak: speak
    }
    var obj2 = {
      name: 'obj2'
    }
    
    obj1.speak() // obj1 (1)
    obj1.speak.call(obj2) // obj2 (2)
    
    

    그래서 상기 코드 에서 ob1. speak () 을 실 행 했 고 speak 함수 내부 의 this 는 ob1 을 가 리 켰 기 때문에 (1)코드 출력 은 당연히 obj 1 입 니 다. 그러나 speak 함수 에 있 는 this 를 obj 2 에 연결 하면 출력 결 과 는 obj 2 가 됩 니 다. 이 결 과 를 통 해 알 수 있 듯 이 명시 적 바 인 딩 의 우선 순 위 는 암시 적 바 인 딩 보다 높 습 니 다. 사실 우 리 는 obj 1. speak. call (obj 2) 을 이렇게 이해 할 수 있 습 니 다.이 줄 코드 는 obb1. speak 에서 간접 적 으로 speak 함수 의 인용 을 얻 었 을 뿐 입 니 다. 앞에서 말 한 암시 적 바 인 딩 이 컨 텍스트 를 잃 어 버 렸 습 니 다. 자, 명시 적 바 인 딩 의 우선 순위 가 암시 적 바 인 딩 보다 높 으 니 new 바 인 딩 과 명시 적 바 인 딩 을 비교 해 보 겠 습 니 다.
    
    function foo(something) {
      this.a = something
    }
    
    var obj1 = {}
    var bar = foo.bind(obj1) //        bar,       this   obj1 (1)
    bar(2) // this    Obj1 ,  obj1.a === 2
    console.log(obj1.a)
    
    var baz = new bar(3) //   new     ,bar   this         baz (2)
    
    console.log(obj1.a)
    console.log(baz.a) 
    
    

    (1) 에서 bar 함수 내부 의 this 는 원래 object 1 을 가리 키 지만 (2) 에서 new 연산 자 호출 을 거 쳐 bar 함수 내부 의 this 는 되 돌아 오 는 인 스 턴 스 를 다시 가리 키 는 것 을 볼 수 있 습 니 다. 이 는 new 바 인 딩 의 우선 순위 가 명시 적 바 인 딩 보다 높다 는 것 을 설명 할 수 있 습 니 다. 이로써 네 가지 바 인 딩 규칙 의 우선 순위 가 나 왔 습 니 다. 각각 new 바 인 딩 의 우선 순위 입 니 다.
    new 바 인 딩 > 명시 적 바 인 딩 > 암시 적 바 인 딩 > 기본 바 인 딩
    화살표 함수 의 this 바 인 딩
    화살표 함 수 는 ES6 의 중요 한 특성 입 니 다. 화살표 함수 의 this 는 외부 (함수 또는 전역) 역할 영역 에 따라 결 정 됩 니 다. 함수 내 this 대상 은 이전에 소개 한 호출 시 바 인 딩 대상 이 아 닌 정의 할 때 있 는 대상 을 말 합 니 다. 예 를 들 어 보 겠 습 니 다.
    
    var a = 1
    var foo = () => {
      console.log(this.a) //         ,  this        
    }
    
    var obj = {
      a: 2
    }
    foo() // 1 ,        
    foo.call(obj) // 1,    , obj     ,        
    
    

    위의 예 에서 보 듯 이 화살표 함수 의 this 강제 적 인 바 인 딩 은 화살표 함수 가 정의 할 때 있 는 역할 영역 에 있 으 며 바 인 딩 을 표시 할 수 없습니다. 예 를 들 어 apply, call 방법 으로 수정 할 수 없습니다. 아래 의 예 를 살 펴 보 겠 습 니 다.
    
    //         
    function Person(name,age) {
      this.name = name
      this.age = age 
      this.speak = function (){
        console.log(this.name)
        //     (     ),this          
      }
      this.bornYear = () => {
        //     2016 ,  new Date().getFullYear()    2016
        //     ,this       
        console.log(new Date().getFullYear() - this.age)
        }
      }
    }
    
    var zxt = new Person("zxt",22)
    
    zxt.speak() // "zxt"
    zxt.bornYear() // 1994
    
    //                
    
    var xiaoMing = {
      name: "xiaoming",
      age: 18 //     18 
    }
    
    zxt.speak.call(xiaoMing)
    // "xiaoming" this    xiaoMing    
    zxt.bornYear.call(xiaoMing)
    // 1994     1998,    this      zxt    
    
    

    따라서 ES6 의 화살표 함 수 는 네 가지 표준 바 인 딩 규칙 을 사용 하지 않 고 현재 의 품사 역할 영역 에 따라 this 를 결정 합 니 다. 구체 적 으로 말 하면 화살표 함 수 는 외층 함수 가 호출 하 는 this 바 인 딩 을 계승 합 니 다. 외층 함수 의 this 바 인 딩 이 어디 에 있 든 간 에.
    작은 매듭
    이상 은 javascript 의 모든 this 바 인 딩 상황 입 니 다. es6 전에 말 한 네 가지 바 인 딩 규칙 은 모든 함수 호출 상황 을 포함 할 수 있 습 니 다. es6 표준 이 실 시 된 후에 함수 의 확장 에 화살표 함 수 를 추 가 했 습 니 다. 이전 과 달리 화살표 함수 의 사용 도 메 인 은 화살표 함수 가 정의 할 때 있 는 역할 도 메 인 에 있 습 니 다.
    그리고 예전 의 네 가지 바 인 딩 규칙 에 있어 모든 규칙 의 호출 조건 을 파악 하면 this 가 도대체 어떤 역할 영역 에 연결 되 었 는 지 잘 이해 할 수 있 습 니 다.

    좋은 웹페이지 즐겨찾기