[javascript] 중첩 된 함수 내의 자바 스크립트 “this”포인터

중첩 된 함수 시나리오에서 “this”포인터가 어떻게 처리되는지에 대한 질문이 있습니다.

다음 샘플 코드를 웹 페이지에 삽입한다고 가정 해 보겠습니다. 중첩 함수 “doSomeEffects ()”를 호출 할 때 오류가 발생합니다. Firebug에서 확인한 결과 중첩 된 함수에있을 때 “this”포인터가 실제로 전역 “window”개체를 가리키고 있음을 나타냅니다. 객체의 함수 내에서 중첩 된 함수를 선언했기 때문에 뭔가를 올바르게 이해하고 있지 않아야합니다. 함수와 관련하여 “로컬”범위를 가져야합니다 (즉, “this”포인터는 다음과 같이 객체 자체를 참조 할 것입니다). 내 첫 “if”문에서 어떻게되는지).

모든 포인터 (말장난 의도 없음)를 주시면 감사하겠습니다.

var std_obj = {
  options : { rows: 0, cols: 0 },
  activeEffect : "none",
  displayMe : function() {

    // the 'this' pointer is referring to the std_obj
    if (this.activeEffect=="fade") { }

    var doSomeEffects = function() {

      // the 'this' pointer is referring to the window obj, why?
      if (this.activeEffect=="fade") { }

    }

    doSomeEffects();
  }
};

std_obj.displayMe();



답변

JavaScript에서 this객체는 실제로 함수 호출 방법을 기반으로합니다.

일반적으로 this개체 를 설정하는 세 가지 방법이 있습니다 .

  1. someThing.someFunction(arg1, arg2, argN)
  2. someFunction.call(someThing, arg1, arg2, argN)
  3. someFunction.apply(someThing, [arg1, arg2, argN])

위의 모든 예에서 this객체는 someThing. 선행 부모 개체없이 함수를 호출하면 일반적으로 대부분의 브라우저에서 개체를 의미하는 전역 개체를 얻을 수 있습니다 window.


답변

이 질문이 가장 많이 찬성 된 질문 중 하나 인 것처럼 보이므로 몇 년이 지난 후에도 화살표 기능을 사용하는 ES6 솔루션을 추가하겠습니다.

var std_obj = {
  ...
  displayMe() {
    ...
    var doSomeEffects = () => {
                        ^^^^^^^    ARROW FUNCTION
      // In an arrow function, the 'this' pointer is interpreted lexically,
      // so it will refer to the object as desired.
      if (this.activeEffect=="fade") { }
    };
    ...
  }
};


답변

this클로저 범위의 일부가 아니므로 호출 사이트에 바인딩 된 함수에 대한 추가 매개 변수로 생각할 수 있습니다. 메서드가 메서드로 호출되지 않으면 전역 개체가 this. 브라우저에서 전역 개체는 window. 예를 들어, 다음 기능을 고려하십시오.

function someFunction() {
}

다음 객체,

var obj = { someFunction: someFunction };

다음과 같은 메서드 구문을 사용하여 함수를 호출하면

obj.someFunciton();

그런 다음 this에 바인딩됩니다 obj.

다음과 같이 someFunction ()을 직접 호출하면

someFunction();

그런 다음 this전역 개체, 즉 window.

가장 일반적인 해결 방법은 다음과 같은 클로저에이를 캡처하는 것입니다.

displayMe : function() {

    // the 'this' pointer is referring to the std_obj      
    if (this.activeEffect=="fade") { }
    var that = this;
    var doSomeEffects = function() {

      // the 'this' pointer is referring to global
      // that, however, refers to the outscope this
      if (that.activeEffect=="fade") { }
    }

    doSomeEffects();
 }      


답변

엔클로저 변수와 “this”에는 차이가 있습니다. “this”는 실제로 함수 호출자에 의해 정의되는 반면 명시 적 변수는 인클로저로 알려진 함수 선언 블록 내부에 그대로 남아 있습니다. 아래 예를 참조하십시오.

function myFirstObject(){
    var _this = this;
    this.name = "myFirstObject";
    this.getName = function(){
       console.log("_this.name = " + _this.name + " this.name = " + this.name);
    }
}

function mySecondObject(){
    var _this = this;
    this.name = "mySecondObject";
    var firstObject = new myFirstObject();
    this.getName = firstObject.getName
}

var secondObject = new mySecondObject();
secondObject.getName();

여기에서 시도해 볼 수 있습니다 :
http://jsfiddle.net/kSTBy/

함수에서 일어나는 일은 “doSomeEffects ()”이며, 명시 적으로 호출됩니다. 이것은 컨텍스트를 의미하거나 함수의 “this”가 창이라는 것을 의미합니다. 만약 “doSomeEffects”가 “myObject”라고 말하는 this.doSomeEffects와 같은 프로토 타입 메소드라면, myObject.doSomeEffects ()는 “this”가 “myObject”가되게합니다.


답변

이 질문을 이해하려면 다음 스 니펫에 대한 출력을 얻으십시오.

var myObject = {
    foo: "bar",
    func: function() {
        var self = this;
        console.log("outer func:  this.foo = " + this.foo);
        console.log("outer func:  self.foo = " + self.foo);
        (function() {
            console.log("inner func:  this.foo = " + this.foo);
            console.log("inner func:  self.foo = " + self.foo);
        }());
    }
};
myObject.func();

위의 코드는 콘솔에 다음을 출력합니다.

outer func:  this.foo = bar
outer func:  self.foo = bar
inner func:  this.foo = undefined
inner func:  self.foo = bar

외부 함수에서 this와 self는 모두 myObject를 참조하므로 둘 다 foo를 올바르게 참조하고 액세스 할 수 있습니다.

그러나 내부 함수에서는 더 이상 myObject를 참조하지 않습니다. 결과적으로 this.foo는 내부 함수에서 정의되지 않은 반면 지역 변수 self에 대한 참조는 범위에 남아 있으며 액세스 할 수 있습니다. (ECMA 5 이전에는 내부 함수에서 전역 창 개체를 참조하는 반면 ECMA 5에서는 내부 함수에서 정의되지 않았습니다.)


답변

Kyle이 설명했듯이 함수 내에서 call또는 apply을 사용 하여 지정할 수 있습니다 this.

코드에 적용된 개념은 다음과 같습니다.

var std_obj = {
    options: {
        rows: 0,
        cols: 0
    },
    activeEffect: "none",
    displayMe: function() {

        // the 'this' pointer is referring to the std_obj
        if (this.activeEffect == "fade") {}

        var doSomeEffects = function() {
            // the 'this' pointer is referring to the window obj, why?
            if (this.activeEffect == "fade") {}
        }

        doSomeEffects.apply(this,[]);
    }
};

std_obj.displayMe();

JsFiddle


답변

또한 “경고있어 이를 통해 클래스 필드에 잠재적으로 잘못된 참조 액세스

class MyListItem {
    constructor(labelPrm) {
        this._flagActive = false;
        this._myLabel = labelPrm;
        labelPrm.addEventListener('click', ()=>{ this.onDropdownListsElementClick();}, false);
    }

    get myLabel() {
        return this._myLabel
    }
    get flagActive(){
        return this._flagActive;
    }

    onDropdownListsElementClick(){console.log("Now'this'refers to the MyListItem itself")}}//end of the class