JavaScript 콜백 범위
-
06-07-2019 - |
문제
콜백 함수에서 내 객체를 참조 할 때 일반 Old JavaScript (프레임 워크 없음)에 문제가 있습니다.
function foo(id) {
this.dom = document.getElementById(id);
this.bar = 5;
var self = this;
this.dom.addEventListener("click", self.onclick, false);
}
foo.prototype = {
onclick : function() {
this.bar = 7;
}
};
이제 새 개체를 만들 때 (DOM이로드 된 후, SPAN#테스트를 통해)
var x = new foo('test');
OnClick 함수 내부의 'this'는 FOO 객체가 아닌 SPAN#테스트를 가리 킵니다.
OnClick 함수 내부의 FOO 객체에 대한 참조는 어떻게 얻습니까?
해결책
(다른 답변에 의견에 숨겨진 설명을 추출했습니다)
문제는 다음 줄에 있습니다.
this.dom.addEventListener("click", self.onclick, false);
여기에서 콜백으로 사용할 함수 객체를 전달합니다. 이벤트가 트리거되면 함수가 호출되지만 이제는 객체 (this)와 관련이 없습니다.
다음과 같이 함수 (객체 참조와 함께) 함수를 래핑하여 문제를 해결할 수 있습니다.
this.dom.addEventListener(
"click",
function(event) {self.onclick(event)},
false);
가변 자체가 할당되었으므로 이것 폐쇄가 생성되면 폐쇄 함수는 나중에 호출 될 때 자체 변수의 값을 기억합니다.
이것을 해결하는 대안적인 방법은 유틸리티 기능을 만드는 것입니다 (그리고 바인딩을 위해 변수를 사용하지 마십시오. 이것):
function bind(scope, fn) {
return function () {
fn.apply(scope, arguments);
};
}
그런 다음 업데이트 된 코드는 다음과 같습니다.
this.dom.addEventListener("click", bind(this, this.onclick), false);
Function.prototype.bind
ECMAScript 5의 일부이며 동일한 기능을 제공합니다. 그래서 당신은 할 수 있습니다 :
this.dom.addEventListener("click", this.onclick.bind(this), false);
아직 ES5를 지원하지 않는 브라우저의 경우 MDN은 다음 SHIM을 제공합니다:
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5 internal IsCallable function
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP
? this
: oThis || window,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}
다른 팁
this.dom.addEventListener("click", function(event) {
self.onclick(event)
}, false);
용 jQuery 이 문제에 대한 해결책을 찾는 사용자는 사용해야합니다. jQuery.proxy
설명은 그 것입니다 self.onclick
JavaScript에서 그것이 의미하는 바를 의미하지는 않습니다. 실제로 의미합니다 onclick
객체의 프로토 타입에서 기능 self
(어떤 식 으로든 참조없이 self
그 자체).
JavaScript에는 함수 만 있으며 C#과 같은 대의원이 없으므로 콜백으로 적용 해야하는 메소드와 객체를 전달할 수 없습니다.
콜백에서 메소드를 호출하는 유일한 방법은 콜백 함수 내에서 직접 호출하는 것입니다. JavaScript 함수는 폐쇄이므로 생성 된 범위에서 선언 된 변수에 액세스 할 수 있습니다.
var obj = ...;
function callback(){ return obj.method() };
something.bind(callback);
문제에 대한 좋은 설명 (지금까지 설명 된 솔루션을 이해하는 데 문제가 있음) 여기에서 사용할 수 있습니다.
이것은 JS의 가장 혼란스러운 지점 중 하나입니다. '이'변수는 가장 로컬 객체에 대한 수단을 의미하지만 함수는 객체이기도하므로 '이'포인트가 있습니다. 다른 미묘한 점이 있지만 나는 그들 모두를 기억하지 못합니다.
나는 보통 'this'를 사용하지 않고 로컬 'me'변수를 정의하고 대신 사용합니다.