질문자 :Felix Kling
이벤트 핸들러를 등록하는 생성자 함수가 있습니다.
function MyConstructor(data, transport) { this.data = data; transport.on('data', function () { alert(this.data); }); } // Mock transport object var transport = { on: function(event, callback) { setTimeout(callback, 1000); } }; // called as var obj = new MyConstructor('foo', transport);
그러나 콜백 내부에 생성된 객체 data
속성에 접근할 수 없습니다. 것 같습니다 this
생성 된 객체를 참조하지만, 또 하나하지 않습니다.
또한 익명 함수 대신 객체 메서드를 사용하려고 했습니다.
function MyConstructor(data, transport) { this.data = data; transport.on('data', this.alert); } MyConstructor.prototype.alert = function() { alert(this.name); };
그러나 동일한 문제를 나타냅니다.
올바른 개체에 어떻게 액세스할 수 있습니까?
당신에 대해 알아야 할 사항 this
this
(일명 "컨텍스트")는 각 함수 내부의 특수 키워드이며 그 값은 함수가 정의된 방법/언제/위치가 아니라 함수가 호출 된 방법에만 의존합니다. 다른 변수와 같은 어휘 범위의 영향을 받지 않습니다(화살표 함수 제외, 아래 참조). 여기 몇 가지 예가 있어요.
function foo() { console.log(this); } // normal function call foo(); // `this` will refer to `window` // as object method var obj = {bar: foo}; obj.bar(); // `this` will refer to `obj` // as constructor function new foo(); // `this` will refer to an object that inherits from `foo.prototype`
더에 대한 내용 this
, 상기보고가 MDN 문서를 .
this
올바르게 참조하는 방법
ECMAScript 6은 람다 함수로 생각할 수 있는 화살표 함수를 도입했습니다. 그들은 자신의 바인딩 this
대신 this
일반 변수처럼 범위 내에서 조회됩니다. .bind
를 호출할 필요가 없습니다. 이것이 유일한 특별한 동작은 아닙니다. 자세한 내용은 MDN 문서를 참조하십시오.
function MyConstructor(data, transport) { this.data = data; transport.on('data', () => alert(this.data)); }
사용하지 마십시오 this
this
특히 액세스하고 싶지 않지만 참조 하는 개체 입니다. 그렇기 때문에 해당 객체를 참조하는 새 변수를 생성하는 것이 쉬운 솔루션입니다. 변수는 어떤 이름을 가질 수 있지만 일반적인 것은 self
와 that
입니다.
function MyConstructor(data, transport) { this.data = data; var self = this; transport.on('data', function() { alert(self.data); }); }
self
는 일반 변수이므로 어휘 범위 규칙을 따르고 콜백 내에서 액세스할 수 있습니다. 이것은 또한 콜백 자체 this
값에 액세스할 수 있다는 장점이 있습니다.
명시 적으로 설정 this
콜백의 - 1 부
값이 자동으로 설정되기 때문에 this
값을 제어할 수 없는 것처럼 보일 수 있지만 실제로는 그렇지 않습니다.
모든 기능을 가지고있어서 .bind
[문서] 와 새로운 함수 반환 this
값으로 결합한다. .bind
를 호출한 것과 정확히 동일한 동작을 하며, this
가 설정한 것뿐입니다. 그 함수가 호출되는 방법이나 시기에 관계없이 this
항상 전달된 값을 참조합니다.
function MyConstructor(data, transport) { this.data = data; var boundFunction = (function() { // parenthesis are not necessary alert(this.data); // but might improve readability }).bind(this); // <- here we are calling `.bind()` transport.on('data', boundFunction); }
이 경우 콜백의 this
MyConstructor
의 this
값에 바인딩합니다.
참고: jQuery에 대한 바인딩 컨텍스트를 사용할 때 jQuery.proxy
[docs]를 사용하세요. 이렇게 하는 이유는 이벤트 콜백을 바인딩 해제할 때 함수에 대한 참조를 저장할 필요가 없기 때문입니다. jQuery는 이를 내부적으로 처리합니다.
설정 this
콜백의 - 2 부
콜백을 허용하는 일부 함수/메소드는 콜백의 this
가 참조해야 하는 값도 허용합니다. 이것은 기본적으로 직접 바인딩하는 것과 동일하지만 함수/메서드가 자동으로 수행합니다. Array#map
[docs] 이 그러한 방법입니다. 서명은 다음과 같습니다.
array.map(callback[, thisArg])
첫 번째 인수는 콜백이고 두 번째 인수는 this
참조해야 하는 값입니다. 다음은 인위적인 예입니다.
var arr = [1, 2, 3]; var obj = {multiplier: 42}; var new_arr = arr.map(function(v) { return v * this.multiplier; }, obj); // <- here we are passing `obj` as second argument
참고 :되는지 여부를 당신이 값 전달할 수 있습니다 this
일반적으로 그 기능 / 방법의 설명서에 언급되어있다. 예를 들어 jQuery의 $.ajax
메서드 [docs] context
라는 옵션을 설명합니다.
이 객체는 모든 Ajax 관련 콜백의 컨텍스트가 됩니다.
일반적인 문제: 객체 메소드를 콜백/이벤트 핸들러로 사용
이 문제의 또 다른 일반적인 징후는 개체 메서드가 콜백/이벤트 핸들러로 사용되는 경우입니다. 함수는 JavaScript에서 일급 시민이며 "메서드"라는 용어는 객체 속성의 값인 함수에 대한 구어체 용어일 뿐입니다. 그러나 해당 함수에는 "포함" 개체에 대한 특정 링크가 없습니다.
다음 예를 고려하십시오.
function Foo() { this.data = 42, document.body.onclick = this.method; } Foo.prototype.method = function() { console.log(this.data); };
this.method
함수는 클릭 이벤트 핸들러로 지정되지만 document.body
를 클릭하면 기록되는 값이 undefined
가 됩니다. 이벤트 핸들러 내부에서 this
Foo
의 인스턴스가 아니라 document.body
참조하기 때문입니다.
처음에 이미 언급했듯이 this
참조하는 것은 함수가 정의되는 방식이 아니라 호출 되는 방식에 따라 다릅니다.
코드가 다음과 같으면 함수에 개체에 대한 암시적 참조가 없다는 것이 더 분명할 수 있습니다.
function method() { console.log(this.data); } function Foo() { this.data = 42, document.body.onclick = this.method; } Foo.prototype.method = method;
사용할 경우, 사용 상기 한 바와 같이 용액을 동일 .bind
바인드 명시 적으로 this
특정 값
document.body.onclick = this.method.bind(this);
또는 익명 함수를 콜백/이벤트 핸들러로 사용하여 객체의 "메소드"로 함수를 명시적으로 호출하고 객체( this
)를 다른 변수에 할당합니다.
var self = this; document.body.onclick = function() { self.method(); };
또는 화살표 기능을 사용하십시오.
document.body.onclick = () => this.method();
Felix Kling 다음은 자식 컨텍스트 내에서 부모 컨텍스트에 액세스하는 몇 가지 방법입니다.
-
bind ()
함수를 사용할 수 있습니다. - context/this에 대한 참조를 다른 변수 안에 저장합니다(아래 예 참조).
- ES6 화살표 기능을 사용합니다.
- 코드, 기능 디자인 및 아키텍처를 변경하십시오. 이를 위해서는 JavaScript의 디자인 패턴에 대한 명령이 있어야 합니다.
1. bind()
함수 사용
function MyConstructor(data, transport) { this.data = data; transport.on('data', ( function () { alert(this.data); }).bind(this) ); } // Mock transport object var transport = { on: function(event, callback) { setTimeout(callback, 1000); } }; // called as var obj = new MyConstructor('foo', transport);
Underscore.js를 사용하는 경우 - http://underscorejs.org/#bind
transport.on('data', _.bind(function () { alert(this.data); }, this));
2. 다른 변수 안에 context/this에 대한 참조를 저장합니다.
function MyConstructor(data, transport) { var self = this; this.data = data; transport.on('data', function() { alert(self.data); }); }
3. 화살표 기능
function MyConstructor(data, transport) { this.data = data; transport.on('data', () => { alert(this.data); }); }
Mohan Dere메서드 호출의 "마법" 구문에 모두 있습니다.
object.property();
개체에서 속성을 가져와 한 번에 호출하면 개체가 메서드의 컨텍스트가 됩니다. 동일한 메서드를 호출하지만 별도의 단계에서 컨텍스트는 대신 전역 범위(창)입니다.
var f = object.property; f();
메서드에 대한 참조를 가져오면 더 이상 개체에 연결되지 않습니다. 평범한 함수에 대한 참조일 뿐입니다. 콜백으로 사용할 참조를 얻을 때도 마찬가지입니다.
this.saveNextLevelData(this.setAll);
여기에서 컨텍스트를 함수에 바인딩합니다.
this.saveNextLevelData(this.setAll.bind(this));
jQuery를 사용하는 경우 bind
이 모든 브라우저에서 지원되지 않으므로 $.proxy
메서드를 사용해야 합니다.
this.saveNextLevelData($.proxy(this.setAll, this));
Guffa당신은 "이"키워드에 대해 알아야한다.
내 견해에 따르면 세 가지 방법으로 "이것"을 구현할 수 있습니다 (자체/화살표 기능/바인드 메서드)
함수의 this
키워드는 다른 언어와 비교하여 JavaScript에서 약간 다르게 동작합니다.
또한 엄격 모드와 비엄격 모드 간에 몇 가지 차이점이 있습니다.
대부분의 경우 this의 값은 함수가 호출되는 방식에 따라 결정됩니다.
실행 중에는 할당으로 설정할 수 없으며, 함수가 호출될 때마다 다를 수 있습니다.
ES5는 함수 호출 방식에 관계없이 this
값을 설정하는 bind() 메서드를 도입했습니다.
this
바인딩을 제공하지 않는 화살표 함수를 도입했습니다(이는 둘러싸는 어휘 컨텍스트의 이 값을 유지합니다).
방법1: Self - Self는 컨텍스트가 변경되더라도 원본 this에 대한 참조를 유지하는 데 사용됩니다. 이벤트 핸들러(특히 클로저)에서 자주 사용되는 기술입니다.
참고 : 이
function MyConstructor(data, transport) { this.data = data; var self = this; transport.on('data', function () { alert(self.data); }); }
방법 2 : 화살표 함수 - 화살표 함수 표현식은 this, arguments, super 또는 new.target 키워드에 대한 자체 바인딩이 없지만 구문상 일반 함수 표현식에 대한 대안입니다.
화살표 함수 표현식은 메서드로 적합하지 않으며 생성자로 사용할 수 없습니다.
참고 : 화살표 함수 표현식
function MyConstructor(data, transport) { this.data = data; transport.on('data',()=> { alert(this.data); }); }
방법 3 : Bind - bind() 메서드는 호출될 때 this
키워드가 새 함수가 호출될 때 제공된 인수 앞에 제공된 일련의 주어진 값과 함께 제공된 값으로 설정되는 새 함수를 만듭니다.
참조: Function.prototype.bind()
function MyConstructor(data, transport) { this.data = data; transport.on('data',(function() { alert(this.data); }).bind(this);
Ashish"컨텍스트"의 문제
"컨텍스트"라는 용어는 때때로 this 에서 참조하는 객체를 참조하는 데 사용됩니다. ECMAScript의 this 와 의미상 또는 기술적으로 맞지 않기 때문에 사용이 부적절합니다.
"컨텍스트" 는 의미를 추가하는 것 또는 추가적인 의미를 제공하는 전후 정보를 둘러싼 상황을 의미합니다. 용어 "콘텍스트"를 참조로 사용되는 ECMAScript를 실행 컨텍스트 일부 코드 실행의 범위 내에있는 모든 매개 변수 범위이며,이.
이것은 ECMA-262 섹션 10.4.2에 나와 있습니다 .
ThisBinding을 호출 실행 컨텍스트의 ThisBinding과 동일한 값으로 설정합니다.
분명히 어떤이는 실행 컨텍스트의 일부임을 나타냅니다.
실행 컨텍스트는 실행 중인 코드에 의미를 추가하는 주변 정보를 제공합니다. 여기에는 thisBinding 보다 훨씬 더 많은 정보가 포함되어 있습니다.
이것의 값은 "컨텍스트"아니다. 실행 컨텍스트의 한 부분일 뿐입니다. 이것은 본질적으로 모든 객체에 대한 호출과 엄격 모드에서 모든 값으로 설정할 수 있는 지역 변수입니다.
RobG첫째, 당신의 명확한 이해가 필요 scope
와의 행동 this
의 맥락에서 키워드 scope
.
this
및 scope
:
JavaScript에는 두 가지 유형의 범위가 있습니다. 그들은:
글로벌 범위
기능 범위
간단히 말해서 전역 범위는 창 개체를 나타냅니다. 전역 범위에서 선언된 변수는 어디에서나 액세스할 수 있습니다.
반면에 함수 범위는 함수 내부에 있습니다. 함수 내부에 선언된 변수는 외부 세계에서 정상적으로 접근할 수 없습니다.
전역 범위의 this
키워드는 창 개체를 참조합니다. this
는 또한 창 개체를 참조합니다. 따라서 this
우리가 선택한 컨텍스트를 나타내기 this
조작하는 방법을 찾을 때까지 항상 창을 참조합니다.
-------------------------------------------------------------------------------- - - - Global Scope - - (globally "this" refers to window object) - - - - function outer_function(callback){ - - - - // Outer function scope - - // Inside the outer function, the "this" keyword - - // refers to window object - - callback() // "this" inside callback also refers to the window object - - } - - - - function callback_function(){ - - - - // Function to be passed as callback - - - - // Here "THIS" refers to the window object also - - } - - - - outer_function(callback_function) - - // Invoke with callback - - - --------------------------------------------------------------------------------
콜백 함수 내에서 this
조작하는 다양한 방법:
여기에 Person이라는 생성자 함수가 있습니다. 그것은라는 속성이 name
과라는 네 가지 방법 sayNameVersion1
, sayNameVersion2
, sayNameVersion3
및 sayNameVersion4
. 네 가지 모두 하나의 특정 작업을 가지고 있습니다. 콜백을 수락하고 호출합니다. 콜백에는 Person 생성자 함수 인스턴스의 name 속성을 기록하는 특정 작업이 있습니다.
function Person(name){ this.name = name this.sayNameVersion1 = function(callback){ callback.bind(this)() } this.sayNameVersion2 = function(callback){ callback() } this.sayNameVersion3 = function(callback){ callback.call(this) } this.sayNameVersion4 = function(callback){ callback.apply(this) } } function niceCallback(){ // Function to be used as callback var parentObject = this console.log(parentObject) }
이제 사람의 생성자에서와 다른 버전의 호출 인스턴스를 만들 수 sayNameVersionX
(X는 1,2,3,4를 의미)와 방법 niceCallback
우리가 조작 할 수있는 방법을 여러 가지 방법으로 볼 수있는 this
받는 참조 내부 콜백을 person
인스턴스를.
var p1 = new Person('zami') // Create an instance of Person constructor
묶다:
this
키워드를 제공된 값으로 설정하여 새 함수를 만드는 것입니다.
sayNameVersion1
및 sayNameVersion2
사용 조작 바인딩 this
콜백 함수.
this.sayNameVersion1 = function(callback){ callback.bind(this)() } this.sayNameVersion2 = function(callback){ callback() }
첫 번째 것은 메소드 자체 내부의 콜백으로 this
그리고 두 번째 콜백은 바인딩된 객체와 함께 전달됩니다.
p1.sayNameVersion1(niceCallback) // pass simply the callback and bind happens inside the sayNameVersion1 method p1.sayNameVersion2(niceCallback.bind(p1)) // uses bind before passing callback
전화:
first argument
의 call
방법으로서 사용되어 this
내부 호출되는 함수 call
에 첨부한다.
sayNameVersion3
용도는 call
조작 this
대신 창 개체, 우리가 만든 사람 객체를 참조하는 방법을.
this.sayNameVersion3 = function(callback){ callback.call(this) }
그리고 다음과 같이 호출됩니다.
p1.sayNameVersion3(niceCallback)
적용하다:
call
과 유사하게 apply
의 첫 번째 인수 this
키워드로 표시될 객체를 참조합니다.
sayNameVersion4
는 apply
을 사용하여 사람 개체를 참조하도록 this
this.sayNameVersion4 = function(callback){ callback.apply(this) }
그리고 다음과 같이 불립니다. 단순히 콜백이 전달되고,
p1.sayNameVersion4(niceCallback)
AL-zamisetTimeout() 은 항상 전역 객체(Window) 와 함께 실행되기 때문에 이것을 setTimeout()
바인딩할 수 없습니다. 콜백 함수에서 this
컨텍스트에 액세스하려면 bind()
를 사용하여 다음과 같이 달성할 수 있습니다.
setTimeout(function(){ this.methodName(); }.bind(this), 2000);
Datta Chanewad이 질문은 this
키워드가 어떻게 작동하는지에 대한 것입니다. this
아래와 같이 다르게 동작합니다.
- 값
this
일반적으로 함수의 실행 상황에 의해 결정된다. - 전역 범위에서
this
전역 개체( window
개체)를 나타냅니다. - 모든 기능에 대해 엄격 모드가 활성화된 경우
this
값은 엄격 모드에서와 같이 undefined
window
개체 대신 undefined
을 참조합니다. - 점 앞에 서 있는 개체는
this
키워드가 바인딩될 개체입니다. -
call()
, bind()
및 apply()
사용하여 이 값을 명시적으로 설정할 수 있습니다. -
new
키워드가 사용되면(생성자) 이것은 생성되는 새 객체에 바인딩됩니다. - 기능이 결합하지 않는 화살표
this
- 대신 this
어휘 바인딩 (즉, 원래의 상황에 따라)
대부분의 답변에서 알 수 있듯이 화살표 함수나 bind()
메서드 또는 Self var를 사용할 수 있습니다. Google JavaScript 스타일 가이드 에서 람다(화살표 기능)에 대한 요점을 인용하겠습니다.
f.bind(this), 특히 goog.bind(f, this)보다 화살표 함수를 사용하는 것을 선호합니다. const self = this를 쓰지 마십시오. 화살표 함수는 예기치 않게 추가 인수를 전달하는 콜백에 특히 유용합니다.
const self = this
보다 람다를 사용할 것을 분명히 권장합니다. = this
따라서 가장 좋은 해결책은 아래와 같이 람다를 사용하는 것입니다.
function MyConstructor(data, transport) { this.data = data; transport.on('data', () => { alert(this.data); }); }
참조:
- https://medium.com/tech-tajawal/javascript-this-4-rules-7354abdb274c
- 화살표 기능 대 결합
Vikas Yadav현재 코드에서 클래스를 사용하는 경우 가능한 다른 접근 방식이 있습니다.
클래스 필드를 지원하면 다음과 같이 만들 수 있습니다.
class someView { onSomeInputKeyUp = (event) => { console.log(this); // This refers to the correct value // .... someInitMethod() { //... someInput.addEventListener('input', this.onSomeInputKeyUp)
확실히 후드 아래에서는 컨텍스트를 바인딩하는 모든 오래된 화살표 기능이 있지만 이 형식에서는 명시적 바인딩보다 훨씬 더 명확해 보입니다.
3단계 Proposal이므로 현재(2018/08/08) 처리 하려면 Babel 과 적절한 Babel 플러그인이 필요합니다.
skyboyer바인딩 DOM2 이후 표준 방법 또 다른 접근 방식 this
항상 (다른 혜택들) 리스너를 제거 할 수 이벤트 리스너 내에서는의이다 handleEvent(evt)
로부터 방법 EventListener
인터페이스 :
var obj = { handleEvent(e) { // always true console.log(this === obj); } }; document.body.addEventListener('click', obj);
handleEvent
사용에 대한 자세한 정보는 다음에서 찾을 수 있습니다. DOM handleEvent: 2000년 이후의 플랫폼 간 표준
Andrea Puddu[xAxisTickFormatting]="xFormat"
과 같이 HTML에서 호출된 xAxisTickFormatting
Ngx
선형 차트 xAxisTickFormatting 함수에 문제가 있었습니다.
선언된 함수에서 내 구성 요소의 변수에 액세스할 수 없습니다. 이 솔루션은 문제를 해결하여 올바른 문제를 찾는 데 도움이 되었습니다.
다음과 같은 기능을 사용하는 대신:
xFormat (value): string { return value.toString() + this.oneComponentVariable; //gives wrong result }
이것을 사용하십시오:
xFormat = (value) => { // console.log(this); // now you have access to your component variables return value + this.oneComponentVariable }
Md. Tazbir Ur Rahman Bhuiyan다른 사람들은 .bind() 메서드를 사용하는 방법에 대해 언급했지만, 특히 누군가가 함께 작동하도록 하는 데 문제가 있는 경우 .then() 과 함께 사용할 수 있는 방법은 다음과 같습니다.
someFunction() .then(function(response) { //'this' wasn't accessible here before but now it is }.bind(this))
주석에서 언급했듯이 대안은 자체 'this' 값이 없는 화살표 함수를 사용하는 것입니다.
someFunction() .then((response)=>{ //'this' was always accessible here })
Josh McGeethis
자바스크립트에서:
this
의 값은 100% 함수가 정의되는 방식이 아니라 호출되는 방식에 따라 결정됩니다. 우리는 'left of the dot rule'에 의해 this
의 값을 비교적 쉽게 찾을 수 있습니다:
- function 키워드를 사용하여 함수를 생성할 때
this
의 값은 호출되는 함수의 점 왼쪽에 있는 객체입니다. - 점의 왼쪽에는 객체가없는 경우 다음의 값
this
함수 내부 (전역 객체 종종 global
Node.js를 및 window
브라우저에서이). this
window
와 같은 것을 사용하는 것보다 덜 명시적이기 때문에 여기에서 this 키워드를 사용하지 않는 것이 좋습니다! - 화살표 함수와 같은 특정 구조가 존재하며
this
값을 수정할 수 Function.prototype.bind()
사용하여 생성된 함수가 있습니다. this
의 값을 수정하는 데 정말 도움이 됩니다.
Node.js의 예
module.exports.data = 'module data'; // This outside a function in node refers to module.exports object console.log(this); const obj1 = { data: "obj1 data", met1: function () { console.log(this.data); }, met2: () => { console.log(this.data); }, }; const obj2 = { data: "obj2 data", test1: function () { console.log(this.data); }, test2: function () { console.log(this.data); }.bind(obj1), test3: obj1.met1, test4: obj1.met2, }; obj2.test1(); obj2.test2(); obj2.test3(); obj2.test4(); obj1.met1.call(obj2);
산출:
출력을 하나씩 안내해 드리겠습니다(두 번째 로그부터 시작하는 첫 번째 로그는 무시).
-
this
점 규칙의 왼쪽 때문에 obj2
test1
obj2.test1();
이라고 불리는 방법을 볼 수 있습니다. . obj2
는 점의 왼쪽에 있으므로 this
값입니다. -
obj2
는 점의 왼쪽에 있지만 test2
bind()
메서드를 통해 obj1
바인딩됩니다. this
값은 obj1
입니다. -
obj2
obj2.test3()
이라는 함수에서 점의 왼쪽에 있습니다. 따라서 obj2
this
의 값이 됩니다. - 이 경우
obj2.test4()
obj2
는 점의 왼쪽에 있습니다. 그러나 화살표 함수에는 this
바인딩이 없습니다. 따라서 처음에 기록된 module.exports
객체인 외부 범위 this
값에 바인딩됩니다. -
call
함수를 사용하여 this
의 값을 지정할 수도 있습니다. 여기에서 원하는 this
값을 인수로 전달할 수 있습니다. 이 경우 obj2
Willem van der Veen출처 : http:www.stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback