콜백 내에서 올바른 'this'에 액세스하는 방법은 무엇입니까?


1425

이벤트 핸들러를 등록하는 생성자 함수가 있습니다.

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);
};

그러나 같은 문제가 있습니다.

올바른 개체에 어떻게 액세스 할 수 있습니까?


95
때때로 나는 어떤 종류의 질문에 푹 빠져서 정식 답변을 작성하기로 결정합니다. 이러한 질문에 대해 백만 번 답변을 받았지만 관련없는 정보에 의해“오염되지 않은”좋은 질문과 답변 쌍을 찾는 것이 항상 가능한 것은 아닙니다. 이것은 그 순간 중 하나이고 그 질문 중 하나입니다 (그리고 나는 지루합니다). 이 유형의 질문에 대해 기존의 정식 질문 / 답변이 실제로 있다고 생각되면 알려 주시면이 질문을 삭제하겠습니다. 개선 제안은 환영합니다!
Felix Kling



3
이것관한 유용한 TypeScript 페이지는 대부분 JS에도 적용됩니다.
Ondra Žižka

답변:


1790

당신이 알아야 할 것 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

사용하지 마십시오 this

실제로는 this특히 액세스하고 싶지 않지만 참조 하는 객체 에 액세스 하십시오 . 그렇기 때문에 쉬운 해결책은 단순히 해당 객체를 참조하는 새 변수를 만드는 것입니다. 변수는 임의의 이름을 가질 수 있지만 일반적인 변수는 selfthat입니다.

function MyConstructor(data, transport) {
    this.data = data;
    var self = this;
    transport.on('data', function() {
        alert(self.data);
    });
}

self일반 변수 이므로 어휘 범위 규칙을 따르고 콜백 내에서 액세스 할 수 있습니다. 또한 this콜백 자체 의 값에 액세스 할 수 있다는 이점이 있습니다 .

명시 적으로 this콜백 세트 -1 부

this값이 자동으로 설정되므로 값을 제어 할 수없는 것처럼 보일 수 있지만 실제로는 그렇지 않습니다.

모든 함수에는 .bind [docs] 메소드가 있습니다.이 메소드 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의 값 MyConstructorthis.

참고 : jQuery에 대한 컨텍스트를 바인딩 할 때는 jQuery.proxy [docs]를 대신 사용하십시오. 이를 수행하는 이유는 이벤트 콜백을 바인딩 해제 할 때 함수에 대한 참조를 저장할 필요가 없기 때문입니다. jQuery는 내부적으로 처리합니다.

ECMAScript 6 : 화살표 기능 사용

ECMAScript 6에는 화살표 함수가 도입 되어 람다 함수로 생각할 수 있습니다. 그들은 자신의 this바인딩 이 없습니다 . 대신 this일반 변수처럼 범위 내에서 조회됩니다. 즉,에 전화 할 필요가 없습니다 .bind. 이것이 유일한 특수 행동은 아닙니다. 자세한 내용은 MDN 설명서를 참조하십시오.

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', () => alert(this.data));
}

this콜백 세트 -2 부

콜백을 허용하는 일부 함수 / 메소드도 콜백 this이 참조해야하는 값을 허용합니다 . 이것은 기본적으로 직접 바인딩하는 것과 동일하지만 함수 / 메소드가 대신합니다. Array#map [문서] 는 그러한 방법입니다. 서명은 다음과 같습니다.

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는 click 이벤트 핸들러로 할당 document.body되지만를 클릭하면 undefined이벤트 핸들러 내에서 의 인스턴스가 아닌을 this참조 하므로 기록 된 값은 document.body입니다 Foo.
처음에 이미 언급했듯이, 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();

39
펠릭스, 나는 전에이 답변을 읽었지만 대답하지 않았습니다. 나는 사람들이 사용 self하고 that참조하는 것에 대해 걱정하고 있습니다 this. this다른 상황에서 사용되는 과부하 변수 이기 때문에 이런 느낌이 듭니다. 반면 self일반적으로 로컬 인스턴스에 해당하며 that일반적으로 다른 객체를 나타냅니다. 나는 당신 이이 규칙을 설정하지 않았다는 것을 알고 있습니다. 나는 그것이 다른 여러 곳에서 나타났습니다. 그러나 그것은 또한 내가 사용하기 시작한 이유 _this입니다. 그 결과.
vol7ron

3
@FelixKling 프로토 타입 함수에서이 함수를 사용하면 (일반적으로) 호출 방식에 관계없이 항상 예상되는 동작이 있다고 가정하는 것이 안전합니까? 프로토 타입 함수 내에서 콜백을 사용할 때 bind (), self 또는 that에 대한 대안이 있습니까?
andig

5
@FelixKling 때때로 Function.prototype.call ()및 에 의존하는 것이 유용 할 수 있습니다 Function.prototype.apply (). 특히 apply ()나는 많은 마일리지를 얻었습니다. bind ()다른 옵션보다 바인드를 사용하는 경우 약간의 오버 헤드 이점이있을 수 있음을 알고 있지만 확실하지는 않지만 습관적으로 만 사용하는 경향이 적습니다 .
Nolo

5
좋은 대답이지만 클래스, 새 클래스 또는 이것을 사용하지 않는 추가 옵션 솔루션을 추가하는 것이 좋습니다.
Aluan Haddad

4
re arrow 기능 "대신, 이것은 일반적인 변수처럼 범위 내에서 조회됩니다." 이 클릭을 완전히 만들어 주셔서 감사합니다. () => this.clicked();)
alphanumeric0101

211

자식 컨텍스트 내에서 부모 컨텍스트에 액세스하는 몇 가지 방법이 있습니다.

  1. bind()기능 을 사용할 수 있습니다 .
  2. 컨텍스트 / this에 대한 참조를 다른 변수 안에 저장하십시오 (아래 예 참조).
  3. ES6 화살표 기능을 사용하십시오 .
  4. 코드 / 함수 디자인 / 아키텍처 변경-이를 위해서는 자바 스크립트의 디자인 패턴 에 대한 명령이 있어야합니다 .

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);

사용중인 경우 -httpunderscore.js : //underscorejs.org/#bind

transport.on('data', _.bind(function () {
    alert(this.data);
}, this));

2 컨텍스트 / 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);
  });
}

1
bind () 옵션은이 객체의 포인터를 다른 객체에서 이것을 전달하는 것만으로도 놀랍습니다 (: 감사합니다!
Stav Bodik

bind ()는 매력처럼 작동합니다. 고마워요 +1 :)
Anjana Silva

56

메소드 호출의 모든 "마법"구문에 있습니다.

object.property();

객체에서 속성을 가져 와서 한 번에 호출하면 객체가 메서드의 컨텍스트가됩니다. 동일한 메소드를 호출하지만 별도의 단계에서 컨텍스트는 글로벌 범위 (창)입니다.

var f = object.property;
f();

메소드의 참조를 얻으면 더 이상 객체에 연결되지 않으며 단지 일반 함수에 대한 참조 일뿐입니다. 콜백으로 사용할 참조를 얻을 때도 마찬가지입니다.

this.saveNextLevelData(this.setAll);

여기서 컨텍스트를 함수에 바인딩 할 수 있습니다.

this.saveNextLevelData(this.setAll.bind(this));

jQuery를 사용하는 경우 모든 브라우저에서 지원되지 않는 $.proxy대신 메소드를 사용해야 bind합니다.

this.saveNextLevelData($.proxy(this.setAll, this));

33

"문맥"의 문제

"컨텍스트"라는 용어는 때때로 이것에 의해 참조되는 객체를 지칭하기 위해 사용된다 . 의미 적으로 또는 기술적으로 ECMAScript의 this 와 맞지 않기 때문에 부적절한 사용입니다 .

"컨텍스트" 는 의미를 추가하는 것을 둘러싼 상황 또는 추가 의미를 부여하는 일부 선행 및 후속 정보를 의미합니다. 용어 "콘텍스트"를 참조로 사용되는 ECMAScript를 실행 컨텍스트 모든 파라미터 범위 인, 및 일부의 실행 코드의 범위 내.

이는 ECMA-262 섹션 10.4.2에 나와 있습니다 .

ThisBinding을 호출 실행 컨텍스트의 ThisBinding과 동일한 값으로 설정하십시오.

이것은 이것이 실행 컨텍스트의 일부 임을 분명히 나타냅니다 .

실행 컨텍스트는 실행중인 코드에 의미를 추가하는 주변 정보를 제공합니다. thisBinding 보다 훨씬 더 많은 정보를 포함합니다 .

의 값 그래서 "컨텍스트"아니다, 그것은 실행 컨텍스트의 한 부분입니다. 본질적으로 모든 객체에 대한 호출과 엄격한 모드에서 모든 값으로 설정할 수있는 로컬 변수입니다.


이 답변에 동의 할 수 없습니다. "실행 컨텍스트"라는 용어의 존재는 다른 "실행"의 사용을 금지하는 것보다 "컨텍스트"의 다른 사용을 금지하지 않습니다. 더 좋은 용어가 this있지만 여기서는 아무 것도 제공되지 않으며 "문맥"에 문을 닫는 것은 너무 늦습니다.
Roamer-1888 2016 년

@ Roamer-1888— 편집 해 주셔서 감사합니다. 네 말이 맞지만 내 주장은 다른 목적으로 "문맥"을 배제한 "실행 문맥"의 존재에 의존하지 않는다. 오히려 그것은 "컨텍스트"가 기술적이고 의미론적인 관점에서 부적절하다는 것을 기반으로합니다. 또한 "this"대신 "context"를 사용하지 않고 있다고 생각합니다. this 또는 thisBinding에 대한 다른 용어를 찾아야 할 이유가 없습니다. 단지 "context"가 실제로 이것 이며, "context"에 있지 않다는 것을 설명하기 위해 어떤 시점에서 난독 화를 의미 합니다. :-)
RobG

나는 이것이 "실행"이 단지 형용사 인 실행 문맥의 한 부분이라는 것을 이미 인정했을 때 이것이 어떤 방식 으로든 "문맥"이 아니라고 말할 수 없다고 생각한다 .
Roamer-1888

@ Roamer-1888—이 시점 이후에는이 대화를 계속하지 않겠습니다. 예, 이것은 이다 부분 실행 컨텍스트의. 그것의 말하는 상황은 팀의 한 선수가 팀입니다 말하는 것과 같다.
RobG

RobG, 당신이 계속하고 싶지 않은 동정. 흥미로운 토론입니다. 시간 내 주셔서 감사합니다.
Roamer-1888

31

"this"키워드에 대해 알아야합니다.

내 관점에 따라 세 가지 방법으로 "this"를 구현할 수 있습니다 (Self / Arrow 함수 / Bind Method)

함수의이 키워드는 JavaScript에서 다른 언어와 약간 다르게 작동합니다.

또한 엄격 모드와 엄격하지 않은 모드 사이에는 약간의 차이가 있습니다.

대부분의 경우이 값은 함수 호출 방법에 따라 결정됩니다.

실행 중에 할당하여 설정할 수 없으며 함수가 호출 될 때마다 다를 수 있습니다.

ES5는 bind () 메소드를 도입하여 호출 방법에 관계없이 함수의 값을 설정합니다.

그리고 ES2015는 자체적으로이 바인딩을 제공하지 않는 화살표 함수를 도입했습니다 (이것은 묶는 어휘 문맥의이 값을 유지합니다).

방법 1 : 자체-컨텍스트가 변경되는 경우에도 자체를 사용하여 원본에 대한 참조를 유지합니다. 이벤트 처리기 (특히 클로저)에서 자주 사용되는 기술입니다.

참조 : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

function MyConstructor(data, transport) {
    this.data = data;
    var self = this;
    transport.on('data', function () {
        alert(self.data);
    });
}

Method2 : 화살표 함수-화살표 함수 표현식은 정규 함수 표현식에 대한 구문 상 컴팩트 한 대안입니다.

this, arguments, super 또는 new.target 키워드에 대한 바인딩이없는 경우에도 마찬가지입니다.

화살표 함수 표현식은 메서드로 적합하지 않으며 생성자로 사용할 수 없습니다.

참조 : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

  function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data',()=> {
        alert(this.data);
    });
}

Method3 : Bind- bind () 메소드는 새로운 함수를 생성합니다.

호출되면이 키워드가 제공된 값으로 설정되어 있으며

새 함수가 호출 될 때 제공된 인수 앞에 주어진 인수 시퀀스가 ​​있습니다.

참조 : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind

  function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data',(function() {
        alert(this.data);
    }).bind(this);

25

먼저 의 문맥에서 키워드에 대한 명확한 이해 scope와 행동 이 필요합니다 .thisscope

this& scope:


there are two types of scope in javascript. They are :

   1) Global Scope

   2) Function Scope

간단히 말하면 전역 범위는 창 개체를 가리 킵니다. 전역 범위에서 선언 된 변수는 어디에서나 액세스 할 수 있습니다. 반면에 함수 범위는 함수 내부에 있습니다. 함수 내부에서 선언 된 변수는 일반적으로 외부 세계에서 액세스 할 수 없습니다. this전역 범위의 키워드는 창 개체를 나타냅니다. this내부 함수는 또한 윈도우 객체 this를 참조하므로 우리가 this선택한 컨텍스트를 나타 내기 위해 조작 할 수있는 방법을 찾을 때까지 항상 윈도우를 참조합니다 .

--------------------------------------------------------------------------------
-                                                                              -
-   Global Scope                                                               -
-   ( globally "this" refers to window object)                                 -     
-                                                                              -
-         function outer_function(callback){                                   -
-                                                                              -
-               // outer function scope                                        -
-               // inside outer function"this" keyword refers to window object -                                                                              -
-              callback() // "this" inside callback also refers window object  -

-         }                                                                    -
-                                                                              -
-         function callback_function(){                                        -
-                                                                              -
-                //  function to be passed as callback                         -
-                                                                              -
-                // here "THIS" refers to 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)

}

이제 person 생성자에서 인스턴스를 생성하고 sayNameVersionX(X는 1,2,3,4 niceCallback참조 ) 메소드 의 다른 버전을 호출 this하여 person인스턴스 를 참조하기 위해 내부 콜백을 조작하는 방법의 수 를 확인하십시오 .

var p1 = new Person('zami') // create an instance of Person constructor

바인딩 :

바인드는 this키워드를 제공된 값으로 설정하여 새 함수를 작성하는 것 입니다.

sayNameVersion1sayNameVersion2사용 바인드 조작 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 argumentcall방법으로 사용 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)

1
답에 관한 건설적인 비판은 인정 될 것입니다!
AL-zami

1
전역 범위의 this 키워드가 반드시 윈도우 객체를 참조하는 것은 아닙니다 . 브라우저에서만 적용됩니다.
랜달 플래그 g

1
@RandallFlagg 나는 브라우저의 관점 에서이 답변을 썼습니다. 필요하다면이 답변을 자유롭게 자유롭게 보내십시오 :)
AL-zami

19

우리는 바인딩이 할 수없는 setTimeout(), 그것을 항상 함께 실행 전역 객체 (창) 당신이 액세스하려는 경우, this다음을 사용하여 콜백 함수의 컨텍스트 bind()우리가 달성 할 수있는 콜백 함수에 :

setTimeout(function(){
    this.methodName();
}.bind(this), 2000);

9
기존 답변과 다른 점은 무엇입니까?
Felix Kling

13

이 질문은 this키워드가 자바 스크립트에서 어떻게 동작하는지에 관한 것입니다. this아래와 같이 다르게 동작합니다.

  1. 의 값 this은 일반적으로 함수 실행 컨텍스트에 의해 결정됩니다.
  2. 전역 범위 this에서 전역 개체 ( window개체)를 나타냅니다.
  3. 엄격 모드는 어떤 기능을 사용할 경우 다음의 값이 this될 것입니다 undefined엄격 모드로는 글로벌 객체를 참조 undefined의 위치에 window객체입니다.
  4. 점 앞에 서있는 객체는이 키워드가 바인딩되는 대상입니다.
  5. 우리는 명시 적으로이 값을 설정할 수 있습니다 call(), bind()그리고apply()
  6. new키워드가 사용 되면 (생성자) 생성되는 새 객체에 바인딩됩니다.
  7. 화살표 함수는 바인딩되지 않습니다. this 대신 this어휘 적으로 바인딩됩니다 (예 : 원래 컨텍스트를 기반으로 함)

대부분의 답변에서 알 수 있듯이 Arrow 함수 또는 bind()Method 또는 Self var를 사용할 수 있습니다 . Google JavaScript 스타일 가이드 에서 람다 (화살표 기능)에 대한 요점을 인용하겠습니다.

f.bind (this), 특히 goog.bind (f, this)보다 화살표 함수를 사용하는 것이 좋습니다. const self = this라고 쓰지 마십시오. 화살표 함수는 콜백에 특히 유용하며 때로는 예기치 않은 추가 인수를 전달합니다.

바인드 또는 람다 대신 람다를 사용하는 것이 좋습니다. const self = this

가장 좋은 해결책은 아래와 같이 람다를 사용하는 것입니다.

function MyConstructor(data, transport) {
  this.data = data;
  transport.on('data', () => {
    alert(this.data);
  });
}

참고 문헌 :

  1. https://medium.com/tech-tajawal/javascript-this-4-rules-7354abdb274c
  2. 화살표 함수 대 바인딩

이 질문은 특히 함수 / 메소드를 콜백으로 사용하는 것에 관한 것입니다. 귀하의 답변이 stackoverflow.com/q/3127429/218196에 더 적합 할 수 있습니다 .
Felix Kling 19

@FelixKling 예 질문은 주요 문제에서 함수 / 메서드를 콜백으로 사용하는 것에 관한 것입니다. this키워드 를 처리했기 때문에 함수 / 메서드를 콜백으로 사용하는 것에 대한 답변을 두 부분으로 나누었습니다 this. 답변을 자유롭게 편집하십시오.
Code_Mode

나는 네 번째 요점을 모호하게 생각한다. 올바른 객체가 점 앞에 서 있지만 컨텍스트가 해당 객체가 아닌 "이 객체를 콜백으로 메소드를 사용할 때의 문제"예제를 고려하십시오 .
bleistift2

7

현재 클래스가 코드에 사용되는 경우 다른 접근 방법이 있습니다.

클래스 필드를 지원 하면 다음과 같은 방법으로 만들 수 있습니다.

class someView {
    onSomeInputKeyUp = (event) => {
        console.log(this); // this refers to correct value
    // ....
    someInitMethod() {
        //...
        someInput.addEventListener('input', this.onSomeInputKeyUp)

후드 아래에는 컨텍스트를 바인딩하는 오래된 좋은 화살표 기능이 있지만이 형식에서는 명시 적 바인딩이 훨씬 더 명확합니다.

3 단계 제안이기 때문에 지금과 같이 처리 하려면 babel 및 적절한 babel 플러그인 이 필요합니다 (08/2018).


2
이것이 정확히 Typescript에서 작동하는 방식입니다 : public methodName = (params) => { body }클래스 내부.
yeyeyerman

5

또 다른 방법, DOM2 이후 표준 방식으로 결합하는 this이벤트 리스너 내에서가, 당신은 항상 청취자 제거 할 수 (다른 혜택들)는 것입니다 handleEvent(evt)로부터 방법 EventListener인터페이스 :

var obj = {
  handleEvent(e) {
    // always true
    console.log(this === obj);
  }
};

document.body.addEventListener('click', obj);

사용에 대한 자세한 정보는 https://medium.com/@WebReflection/dom-handleevent-a-cross-platform-standard-since-year-2000-5bf17287fd38handleEvent 에서 확인할 수 있습니다.


0

this JS에서 :

thisJS 의 값은 함수가 어떻게 정의되는지가 아니라 함수가 어떻게 호출되는지에 따라 100 % 결정됩니다. 우리는 '점 규칙의 왼쪽'this의해 값을 비교적 쉽게 찾을 수 있습니다 .

  1. function 키워드를 사용하여 함수를 생성하면 this 은 호출 된 함수의 점 왼쪽에있는 객체입니다.
  2. 점의 왼쪽에 객체가 없으면 this함수 내부 의 값 은 종종 전역 객체입니다 ( global노드, window브라우저). this키워드는 다음과 같은 것을 사용하는 것보다 덜 명시 적이므로 키워드를 사용하지 않는 것이 좋습니다.window !
  3. 화살표 함수 및 Function.prototype.bind()의 값을 수정할 수 있는 함수를 사용하여 작성된 함수와 같은 특정 구성이 있습니다 this. 이는 규칙의 예외이지만 값을 수정하는 데 실제로 도움이됩니다 this.

nodeJS의 예

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);

산출:

여기에 이미지 설명을 입력하십시오

첫 번째 로그는 두 번째부터 시작하여 무시하고 출력 1-1을 안내합니다.

  1. this입니다 obj2때문에 도트 규칙의 왼쪽에, 우리는 어떻게 볼 수 test1라고합니다 obj2.test1();. obj2점의 왼쪽에 있으므로 this값이됩니다.
  2. obj2점의 왼쪽에 있지만 메서드 test2obj1통해 바인딩됩니다 bind(). 따라서 this값은 obj1입니다.
  3. obj2라는 함수에서 점의 왼쪽에 obj2.test3()있습니다. 따라서 obj2의 값이 this됩니다.
  4. 이 경우 : obj2.test4() obj2점의 왼쪽입니다. 그러나 화살표 기능에는 자체 this바인딩 이 없습니다 . 따라서 this외부 스코프 의 값에 바인딩됩니다 .module.exports 처음에 기록 된 개체 인 .
  5. 함수 this를 사용하여 값을 지정할 수도 call있습니다. 여기서 우리는 원하는 this값을 인수로 전달할 수 있습니다 obj2.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.