중첩 된 함수 시나리오에서 “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
개체 를 설정하는 세 가지 방법이 있습니다 .
someThing.someFunction(arg1, arg2, argN)
someFunction.call(someThing, arg1, arg2, argN)
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();
답변
또한 “경고있어 이를 통해 클래스 필드에 잠재적으로 잘못된 참조 액세스 “
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