javascript 에서 this 의 작업 원리 및 주의사항

8614 단어 웹 개발
JavaScript 에서 this 의 개념 이 비교적 복잡 하 다.대상 을 대상 으로 프로 그래 밍 하 는 것 을 제외 하고 this 아무 데 나 쓸 수 있어.이 글 은 this 를 소개 했다. 어떤 문 제 를 일 으 킬 지, 그리고 this 의 관련 예.이것 에 근거 하여 있 는 위치 에서 그것 을 이해 하면 상황 은 대략 세 가지 로 나 눌 수 있다.
함수 보통 함 축 된 매개 변수 입 니 다.
2. 함수 외 (최상 위 역할 영역 에서): 브 라 우 저 에서 this 전역 대상 을 가리킨다.Node. js 에 서 는 모듈 (module) 내 보 내기 (exports) 를 말 합 니 다.
3. eval () 에 전 달 된 문자열: eval () 이 직접 호출 된다 면 this 현재 대상eval () 이 간접 적 으로 호출 된다 면 this 전체의 대상 을 가리킨다.
 
이 몇 가지 분류 에 대해 우 리 는 상응하는 테스트 를 했다.
함수 중의 this 함 수 는 기본적으로 JS 에서 호출 될 수 있 는 모든 구 조 를 대표 할 수 있 기 때문에 이것 도 가장 흔히 볼 수 있 는 this 를 사용 합 니 다. 의 장면, 함수 이불 은 다음 과 같은 세 가지 역할 로 나 눌 수 있 습 니 다.
 실제 함수 에서 this
 
실제 함수 에서 this 의 값 은 그것 이 처 한 문맥 의 패턴 에 달 려 있다.
Sloppy 모드: this 전역 대상 (브 라 우 저 에서 window) 을 말 합 니 다.
function sloppyFunc() {
    console.log(this === window); // true
}
sloppyFunc();

Strict 모드: this 값 은 undefined 입 니 다.
function strictFunc() {
    '
    use strict';
    console.log(this === undefined); // true
}
strictFunc();

 
this 함수 의 함 축 된 매개 변수 이기 때문에 값 은 항상 같 습 니 다.하지만 콜 () 이나 apply () 를 사용 하 는 방법 으로 this 의 값 을 표시 할 수 있 습 니 다.
function func(arg1, arg2) {
    console.log(this); // 1
    console.log(arg1); // 2
    console.log(arg2); // 3
}
func.call(1, 2, 3); //(this, arg1, arg2) 
func.apply(1, [2, 3]); // (this, arrayWithArgs)

구조 기 중의 this
new 하나의 함 수 를 구조 기로 사용 하 다.new 작업 은 새로운 대상 을 만 들 고 이 대상 을 this 로 통과 합 니 다. 구조 기 에 들어가다.
var savedThis; 
function Constr() {
    savedThis = this;
}
var inst = new Constr();
console.log(savedThis === inst); // true

JS 중 new 조작의 실현 원 리 는 대략 아래 의 코드 와 같다 (더욱 정확 한 실현 은 여 기 를 보십시오. 이 실현 도 비교적 복잡 합 니 다).
function newOperator(Constr, arrayWithArgs) {
    var thisValue = Object.create(Constr.prototype);
    Constr.apply(thisValue, arrayWithArgs);
    return thisValue;
}

1.3  방법 중의 this
방법 중 this 전통 적 인 대상 언어: this 가리 키 는 수신 자, 즉 이 방법 이 있 는 대상 을 포함한다.
var obj = {
    method: function () {
        console.log(this === obj); // true
    }
}
obj.method();
  • 실 함수
  • 구조 기
  • 방법
  • 역할 영역 중의 this 는 브 라 우 저 에서 역할 영역 은 전역 역할 영역 입 니 다. this 이 전역 대상 (window 처럼) 을 말 합 니 다.
  •  
    console.log(this === window); // true 
    

    Node. js 에서 당신 은 보통 module 에서 함 수 를 실행 합 니 다.따라서 최고급 역할 영역 은 매우 특별한 모듈 역할 영역 (module scope) 입 니 다.
    // `global` (not `window`) refers to global object:
    console.log(Math === global.Math); // true
    // `this` doesn’t refer to the global object: 
    console.log(this !== global);// true
    // `this` refers to a module’s exports: 
    console.log(this === module.exports);// true
  • eval () 중의 this
  • eval () 은 직접 (이 함수 이름 'eval' 을 호출 하여) 또는 간접 (다른 방식 으로 호출 할 수 있 습 니 다. 예 를 들 어 call () 을 통 해 호출 할 수 있 습 니 다.더 많은 세부 사항 을 알 고 싶 으 면 여 기 를 보 세 요.
    // Real functions 
    function sloppyFunc() {
        console.log(eval('this') === window); // true
    }
    sloppyFunc();
    function strictFunc() { 
        '
        use strict';
        console.log(eval('this') === undefined); // true
    } 
    strictFunc(); // Constructors var savedThis;
    function Constr() {
        savedThis = eval('this');
    }
    var inst = new Constr();
    console.log(savedThis === inst); // true // Methods
    var obj = { 
        method: function () {
            console.log(eval('this') === obj); // true  
        }
    }
    obj.method();
  • this 와 관련 된 함정
  • 너 는 아래 에 소개 할 세 개 와 this 를 조심해 야 한다. 관련 된 함정.아래 의 예 에서 Strict 모드 (strict mode) 를 사용 하면 코드 의 안전성 을 높 일 수 있 음 을 주의해 야 합 니 다.실제 함수 에서 this 의 값 은 undefined 입 니 다. 문제 가 생 겼 을 때 경 고 를 받 을 수 있 습 니 다.
    4.1  new 를 사용 하 는 것 을 잊 어 버 리 세 요. 만약 당신 이 new 를 사용 하여 구조 기 를 호출 하지 않 았 다 면, 사실은 실제 함 수 를 사용 하고 있 는 것 입 니 다.그래서 this 는 네가 예상 한 값 이 아니다.Sloppy 모드 에서 this 가리 키 는 게 window 예요. 전역 변 수 를 만 들 것 입 니 다:
    function Point(x, y) {
        this.x = x;
        this.y = y;
    }
    var p = Point(7, 5); // we forgot new! 
    console.log(p === undefined); // true // Global variables have been created: console.log(x); // 7 
    console.log(y); // 5

    하지만 strict 모드 를 사용한다 면 경 고 를 받 을 수 있 습 니 다 (this = = = undefined):
    function Point(x, y) {
        '
        use strict';
        this.x = x;
        this.y = y;
    }
    var p = Point(7, 5); // TypeError: Cannot set property 'x' of undefined

    4.2 부적 절 한 사용 방법 만약 에 당신 이 방법의 값 을 직접 얻 으 면 (그것 을 호출 하 는 것 이 아니 라) 이 방법 을 함수 로 사용 하 는 것 입 니 다.하나의 방법 을 하나의 매개 변수 로 함수 나 호출 방법 에 전달 하려 면 이렇게 할 수 있 습 니 다.setTimeout () 과 등록 이벤트 핸들 (event handlers) 이 바로 이런 상황 입 니 다.나 는 callIt () 방법 으로 이 장면 을 모 의 할 것 이다.
    /** Similar to setTimeout() and setImmediate() */ 
    function callIt(func) { 
        func();
    }

    만약 Sloppy 모드 에서 하나의 방법 을 함수 로 호출 한다 면 * this * 는 전역 대상 을 가리 키 기 때문에 나중에 만 든 것 은 전역 변수 입 니 다.
    var counter = {
        count: 0, // Sloppy-mode method
        inc: function () { this.count++; }
    }
    callIt(counter.inc); // Didn’t work:
    console.log(counter.count); // 0 // Instead, a global variable has been created // (NaN is result of applying ++ to undefined):
    console.log(count); // NaN

    만약 당신 이 Strict 모드 에서 이렇게 한다 면, this 는 undefined 입 니 다. 당신 은 여전히 원 하 는 결 과 를 얻 지 못 할 것 입 니 다. 그러나 적어도 당신 은 경 고 를 받 을 것 입 니 다.
    var counter = {
        count: 0, // Strict-mode method
        inc: function () { 'use strict'; this.count++; } 
    }
        callIt(counter.inc); // TypeError: Cannot read property 'count' of undefined
        console.log(counter.count);

    예상 한 결 과 를 얻 으 려 면 bind () 를 사용 하 십시오.
    var counter = {
        count: 0,
        inc: function () {
            this.count++;
        }
    } 
    callIt(counter.inc.bind(counter));
    // It worked! console.log(counter.count); // 1

    bind () 는 항상 this 값 을 counter 로 설정 할 수 있 는 값 을 만 들 었 습 니 다. 의 함수.
    4.3 this 를 숨 깁 니 다. 방법 에서 함 수 를 사용 할 때 함수 가 자신의 this 라 는 것 을 무시 합 니 다. 라 고 적 었 다.이것 또 방법 과 다 르 기 때문에 너 는 이 두 개의 this 를 섞어서 사용 하 다.구체 적 인 것 은 아래 코드 를 보십시오.
    var obj = {
        name: '
        Jane'
        , 
    friends: [ 'Tarzan', 'Cheeta' ],
    loop: function () { 
        '
        use strict';
        this.friends.forEach(
            function (friend) { 
                console.log(this.name+' 
                knows '
                +friend);
            } ); 
        } 
    }; 
    obj.loop(); // TypeError: Cannot read property 'name' of undefined

    위의 예 에서 함수 중의 this. name 함수 의 this 때문에 사용 할 수 없습니다. 이것 과 방법 loop () 의 this 다르다다음은 이 문 제 를 해결 하기 위해 세 가지 방향 을 제공 했다.
  • that = this, 변수 에 값 을 부여 합 니 다. 이렇게 하면 this 를 뚜렷이 드러나다 this 를 저장 하 는 데 사용 되 는 변수 이름 이기 도 합 니 다). 그 다음 에 그 변 수 를 사용 합 니 다.
  • loop: function () { 
        '
        use strict'
        var that = this; 
        this.friends.forEach(function (friend) { 
            console.log(that.name+' knows '+friend); 
        }); 
    }
  • bind()。bind () 를 사용 하여 함수, 이 함수 의 this 를 만 듭 니 다. 항상 당신 이 전달 하고 자 하 는 값 이 저 장 됩 니 다. (아래 이 예 에서 방법의 this):
  • loop: function () { 
        '
        use strict'
        this.friends.forEach(function (friend) { 
            console.log(this.name+' knows '+friend); 
        }.bind(this)); 
    }
  • foreach 의 두 번 째 매개 변 수 를 사용 합 니 다.foreach 의 두 번 째 매개 변 수 는 반전 함수 로 들 어 갑 니 다. 사용 하 다
  • loop: function () { 
        '
        use strict'; 
        this.friends.forEach(
            function (friend) { 
                console.log(this.name+' knows '+friend); 
            }, 
        this); 
    }
  • 최고의 실천
  • 이론 적 으로 나 는 실제 함수 가 자신 만 의 this 가 아니 라 상술 한 해결 방안 도 이 사상 에 따른다 고 생각한다.ECMAScript 6 는 화살표 함수 (arrow function) 로 이 효 과 를 실현 합 니 다. 화살표 함 수 는 자신의 this 가 없습니다. 의 함수.이런 함수 에서 당신 은 마음대로 this 를 사용 할 수 있 으 며, 암시 적 인 존재 가 있 는 지 없 는 지 걱정 할 필요 가 없습니다.
    loop: function () { 
        '
        use strict'; // The parameter of forEach() is an arrow function 
        this.friends.forEach(friend => { // `this` is loop’s `this` 
            console.log(this.name+' knows '+friend); 
        }); 
    }

    나 는 어떤 API 들 이 이것 을 실제 함수 의 추가 매개 변수 로 사용 하기:
    beforeEach(function () { 
        this.addMatchers({ 
            toBeInRange: function (start, end) {
                ... 
            } 
        }); 
    });

    내 현적 인 파 라 메 터 를 외 현적 인 모양 으로 써 서 입력 하면 코드 가 더욱 잘 이해 되 고 화살표 함수 의 요구 도 일치 합 니 다.
    beforeEach(api => { api.addMatchers({ toBeInRange(start, end) { ... } }); });

    좋은 웹페이지 즐겨찾기