programing

콜백 내에서 올바른 'this'에 액세스하는 방법

copysource 2022. 9. 22. 22:49
반응형

콜백 내에서 올바른 'this'에 액세스하는 방법

이벤트 핸들러를 등록하는 컨스트럭터 함수가 있습니다.

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('context'라고도 함)는 각 함수의 내부에 있는 특별한 키워드이며 함수의 값은 함수의 호출 방법, 시간, 위치가 아니라 함수의 호출 방법에 따라 달라집니다.다른 변수와 같이 어휘 범위의 영향을 받지 않습니다(화살표 기능은 제외, 아래 참조).다음은 몇 가지 예입니다.

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`

자세한 것은, 「 」의 한 것에 는, 을 해 주세요.thisMDN 매뉴얼을 참조하십시오.


this

화살표 기능 사용

ECMAScript 6은 람다 함수로 간주할 수 있는 화살표 함수를 도입했습니다.그들은 자기 것이 없다.this ,,는this일반 변수와 마찬가지로 범위 내에서 검색됩니다., 전화할 .bind특별한 동작은 이것뿐만이 아닙니다.MDN MDN MDN MDN MDN MDN MDN MDN MDN MDN MDN MDN MDN MDN MDN MDN MDN MDN MDN MDN MDN MDN MDN 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는 일반 변수이며 어휘 스코프 규칙을 준수하며 콜백 내에서 액세스할 수 있습니다., 이 URL에는 할 수 .this★★★★★★★★★★★★★★★★★★★★

으로 설정하다this- 1 - 콜백1

경우 을 제어할 수 없는 수 .this값은 자동으로 설정되지만 실제로는 그렇지 않습니다.

모든 함수에는 메서드가 있습니다.이 [docs]메서드는 다음과 같은 새로운 함수를 반환합니다.this가치에 얽매여 있습니다.이 부르던 같은 을 하고 있습니다..bind만 on, 그그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);
}

의 「」를 .thisMyConstructor의 »this.

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

★★this- - 콜백2

또는 콜백이 .this참조할 필요가 있습니다.이는[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의 메서드는 다음과 같은 옵션을 설명합니다.context:

이 오브젝트는 모든 Ajax 관련 콜백의 컨텍스트가 됩니다.


일반적인 문제:오브젝트 메서드를 콜백/이벤트 핸들러로 사용

이 문제의 또 다른 일반적인 징후는 오브젝트 메서드가 콜백/이벤트 핸들러로 사용되는 경우입니다.함수는 JavaScript에서 1등급 시민이며, "메서드"라는 용어는 객체 속성의 값인 함수의 구어체일 뿐입니다.그러나 이 함수에는 "포함" 객체에 대한 특정 링크가 없습니다.

다음 예를 생각해 보겠습니다.

function Foo() {
    this.data = 42,
    document.body.onclick = this.method;
}

Foo.prototype.method = function() {
    console.log(this.data);
};

★★this.method만, 「클릭 핸들러」의 는,document.body클릭하면 는 값은 """가 .undefined핸들러 에는 「」가 있기 때문에this 하다를 .document.bodyFoo.
것이 있을까요?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();

다음은 자녀 컨텍스트 내의 부모 컨텍스트에 액세스하는 몇 가지 방법입니다.

  1. .bind()★★★★★★ 。
  2. 콘텍스트/이러한 참조를 다른 변수 안에 저장합니다(아래 예 참조).
  3. ES6 Arrow 기능을 사용합니다.
  4. 코드, 함수 설계 및 아키텍처를 변경합니다.이를 위해서는 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/ #http://http://underscorejs.org/

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

2. 콘텍스트/이러한 참조를 다른 변수 안에 저장합니다.

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

모두 메서드를 호출하는 "매직" 구문입니다.

object.property();

개체에서 속성을 가져와 한 번에 호출하면 개체가 메서드의 컨텍스트가 됩니다.같은 메서드를 호출하지만 다른 순서로 호출하는 경우 컨텍스트는 글로벌스코프(창)가 됩니다

var f = object.property;
f();

메서드의 참조를 가져오면 더 이상 객체에 연결되지 않습니다.단순한 함수에 대한 참조일 뿐입니다.콜백으로 사용하는 참조를 취득했을 때에도 같은 일이 발생합니다.

this.saveNextLevelData(this.setAll);

여기서 컨텍스트를 함수에 바인드합니다.

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

를 사용하는 jQuery를 해야 .$.proxy대 method method 대 method 、 대메 、 대 method 、 method method method method method method method 。bind모든 되는 것은 .

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

할까 "this" 키워드에 대해 알고 있습니다.

제 견해로는, 「이것」을 3가지 방법으로 실장할 수 있습니다. (자체/화살표 기능/바인드 방법)

함수는 A입니다.this자바스크립트

또한 strict 모드와 non-strict 모드 사이에는 몇 가지 차이점도 있습니다.

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

실행 중 할당으로 설정할 수 없으며 함수를 호출할 때마다 다를 수 있습니다.

되었습니다.this불리고 있든

ES2015를 않는 했습니다.this바인딩(binding)

방법 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.protype.bind()

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

'콘텍스트'에 관한 문제

"콘텍스트"라는 용어는 때때로 이것에 의해 참조되는 개체를 가리키는 데 사용됩니다.ECMAScript 의미적으로나 기술적으로 맞지 않기 때문에 부적절합니다.

"내용"은 의미를 더하는 무언가를 둘러싼 상황 또는 의미를 더하는 일부 전후 정보를 의미한다."콘텍스트"라는 용어는 ECMAScript에서 실행 컨텍스트를 가리키기 위해 사용됩니다. 실행 컨텍스트는 일부 실행 코드의 범위 내에 있는 모든 파라미터, 범위 이 컨텍스트입니다.

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

ThisBinding을 호출 실행 컨텍스트의 ThisBinding과 같은 값으로 설정합니다.

이는 이것이 실행 컨텍스트의 일부임을 명확하게 나타냅니다.

실행 컨텍스트는 실행 중인 코드에 의미를 부여하는 주변 정보를 제공합니다.파일에는 thisBinding뿐만 아니라 훨씬 더 많은 정보가 포함되어 있습니다.

이것의 가치는 "문맥"이 아닙니다.실행 컨텍스트의 일부일 뿐입니다.기본적으로 로컬 변수이며 콜에 의해 임의의 오브젝트 및 완전 모드로 설정할 수 있습니다.

먼저 의 컨텍스트에서 키워드와 동작을 명확히 이해해야 합니다.

this&scope:


JavaScript에는 두 가지 유형의 스코프가 있습니다.다음과 같은 것이 있습니다.

  1. 글로벌 범위

  2. 기능 범위

즉, 글로벌스코프는 윈도 오브젝트를 참조합니다.글로벌 범위에서 선언된 변수는 어디에서나 액세스할 수 있습니다.

반면 함수 범위는 함수 내부에 있습니다.함수 내부에서 선언된 변수는 외부에서 정상적으로 액세스할 수 없습니다.

글로벌 스코프의 키워드는 window 객체를 참조합니다.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이라는 생성자 함수가 있습니다.여기에는 라는 속성과 , , , , , , 라는4개의 메서드가 있습니다.이들 4개 모두 1개의 특정 태스크를 가지고 있습니다.콜백을 받아들여 호출합니다.콜백에는 Person Constructor 함수 인스턴스의 이름 속성을 기록하는 특정 작업이 있습니다.

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

이제 퍼스널 컨스트럭터에서 인스턴스를 만들고 여러 버전의 (X는 1,2,3,4를 참조함) 메서드를 호출하여 인스턴스를 참조하도록 내부 콜백을 조작할 수 있는 방법을 확인합니다.

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

바인드:

바인드는 키워드가 지정된 값으로 설정된 새로운 함수를 작성하는 것입니다.

sayNameVersion1 ★★★★★★★★★★★★★★★★★」sayNameVersion2bind를 사용하여 콜백 함수를 조작합니다.

this.sayNameVersion1 = function(callback){
    callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
    callback()
}

첫 번째는 메서드 자체의 콜백으로 바인드됩니다.두 번째 콜백은 오브젝트가 바인드된 상태로 전달됩니다.

p1.sayNameVersion1(niceCallback) // pass simply the callback and bind happens inside the sayNameVersion1 method

p1.sayNameVersion2(niceCallback.bind(p1)) // uses bind before passing callback

호출:

메서드의 는 연결된 함수의 내부로 사용됩니다.

sayNameVersion3는 를 조작하여 윈도 오브젝트가 아닌 작성한 사용자 오브젝트를 참조하기 위해 사용합니다.

this.sayNameVersion3 = function(callback){
    callback.call(this)
}

그 이름은 다음과 같습니다.

p1.sayNameVersion3(niceCallback)

적용:

와 마찬가지로 의 첫 번째 인수는 키워드로 표시되는 오브젝트를 나타냅니다.

sayNameVersion4사용자 객체를 참조하기 위해 조작하기 위해 사용

this.sayNameVersion4 = function(callback){
    callback.apply(this)
}

그리고 이렇게 불려요.단순히 콜백이 전달됩니다.

p1.sayNameVersion4(niceCallback)

할 수 .setTimeout()글로벌 오브젝트(윈도)함께 항상 실행되기 때문입니다.에 액세스 하고 싶은 경우this 할 수 .bind()콜백 함수는 다음과 같이 실행할 수 있습니다.

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

는 어떻게 이 문제를 할 수 있을까 것입니다.this자바스크립트 this같이 합니다.

  1. 「」의 값this는 보통 함수 실행 컨텍스트에 의해 결정됩니다.
  2. 스코프에서는, 「」가 됩니다.this 오브젝트를하고 있습니다.window★★★★★★★★★★★★★★★★★★」
  3. strict 이 되어 있는 는, 「strict」의 값이 .this 되다undefined는 strict를 합니다.undefinedwindow★★★★★★ 。
  4. 앞에 오브젝트는 점 앞에 있는 입니다.this키워드는 필수입니다.
  5. 이 은 ' 낫다'로 할 수 .call(),bind() , , , , 입니다.apply()
  6. ?new이치노이것은 작성되는 새로운 오브젝트에 바인드 됩니다.
  7. 않습니다.this - 대,,this 문맥에 합니다). (즉, '원래의문맥에 근거합니다.)

대부분의 답변에서 알 수 있듯이 화살표 기능 또는 Method 또는 Self var를 사용할 수 있습니다.Google JavaScript Style Guide에서 람다(화살표 함수)에 대한 요점을 인용합니다.

f.bind(이것), 특히 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. arrow-vs-vs-vs-flashed

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

클래스 필드를 지원하면 다음과 같이 만들 수 있습니다.

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

확실히 후드 아래에서는 콘텍스트를 묶는 오래된 좋은 화살표 기능이지만, 이 형태에서는 명시적인 바인딩이 훨씬 더 명확해 보입니다.

Stage 3 Proposal이기 때문에, 현시점에서는 Babel과 적절한 Babel 플러그인이 필요합니다(2018년 8월).

가 문제가 요.Ngx 차트xAxisTickFormatting HTML에서 호출된 함수입니다.[xAxisTickFormatting]="xFormat".

선언된 함수에서 구성 요소의 변수에 액세스할 수 없습니다.이 솔루션은 문제를 해결하고 올바른 문제를 찾는 데 도움이 되었습니다.

다음과 같은 기능을 사용하는 대신:

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
 }

또 다른 접근법입니다.이것은 DOM2 이후 표준적인 바인드 방식입니다.this이벤트 리스너 내에서 항상 리스너를 제거할 수 있는 것은 (다른 이점 중)handleEvent(evt)EventListener★★★★★★★★★★★★★★★★★★:

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

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

" " " " "handleEventDOM handle Event: 2000년 이후 크로스 플랫폼 표준

.bind() 메서드를 사용하는 방법에 대해 다른 사용자가 언급했지만, 특히 다른 사용자가 함께 작업하는 데 문제가 있는 경우 .then() 메서드를 함께 사용할 수 있는 방법이 있습니다.

someFunction()
.then(function(response) {
    //'this' wasn't accessible here before but now it is
}.bind(this))

코멘트에 기재되어 있듯이, 독자적인 「이」값을 가지지 않는 화살표 기능을 사용하는 것도 대안이 될 수 있습니다.

someFunction()
.then((response)=>{
    //'this' was always accessible here
})

thisJavaScript:

「」의 값this자바스크립트의 경우 함수의 정의 방식이 아니라 함수의 호출 방식에 따라 100% 결정됩니다. 수 .this점의 왼쪽 규칙:

  1. 값 " " " 가 됩니다.this의 점 에 있는 입니다.
  2. 의 있지 않은 값 " " " " " "this는 종종 오브젝트대부분은 글로벌 입니다.globalNode 및 Node.js의 »에 있습니다.window★★★★★★★★★★★★★★★★★★★★★」이 하지 않습니다.this서의 키워드는, 「명료하지 않다」와 같은 것을 보다 덜 에, 서의 키워드입니다.window!
  3. 기능을 해서 만든 같은 .Function.prototype.bind()치를의 값을 할 수 this이것들은 규칙의 예외입니다만, 이러한 예외는 이 규칙의 가치를 고정하는 데 매우 도움이 됩니다.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);

출력:

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

출력에 대해 하나씩 설명하겠습니다(두 번째 로그부터 시작하는 첫 번째 로그는 무시합니다.

  1. thisobj2규칙의 알 수 요.test1라고 합니다.obj2.test1();obj2, 「점」이 됩니다.thisdiscloss.discloss 。
  2. 그럼에도 불구하고.obj2 점, 점, 왼쪽 점, 왼쪽 점, 왼쪽 점, 왼쪽 점, 왼쪽 점, 왼쪽 점, 왼쪽 점, 왼쪽 점.test2 속박되어 있다obj1 the를 bind()★★★★★★this는 「」입니다.obj1.
  3. obj2은 '보다'라는입니다.obj2.test3().그러므로obj2가치가 있다this.
  4. 「」는 다음과 같습니다.obj2.test4() obj2점의 왼쪽입니다.화살표 가 없습니다.this 해서 '아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아,this값, 즉 「」, 「」module.exports처음에 기록했던 오브젝트
  5. '보다 낫다'의 도 있습니다.thiscall여기 시킬 수 있습니다.this로서의 값)obj2★★★★★★★★★★★★★★★★★★,

언급URL : https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback

반응형