var self = this?


182

이벤트 핸들러에 대한 콜백의 범위 변경으로 인스턴스 메소드를 사용 this에서 "내 예""바로 콜백이라고 무엇이든을" . 내 코드는 다음과 같습니다

function MyObject() {
  this.doSomething = function() {
    ...
  }

  var self = this
  $('#foobar').bind('click', function(){
    self.doSomethng()
    // this.doSomething() would not work here
  })
}

작동하지만 이것이 최선의 방법입니까? 나에게 이상해 보인다.


15
객체 self가 있으므로 피해야 하며 window.self자신의 selfvar 선언을 잊어 버린 경우 (예 : 코드를 움직일 때) 실수로 사용할 수 있습니다 . 스팟 / 디버그가 성 가실 수 있습니다. 같은 것을 사용하는 것이 _this좋습니다.
Alastair Maw


3
로부터 자바 스크립트 튜토리얼 "의 값은 this자바 스크립트의 동적입니다 기능이 때 결정됩니다. 전화 가 선언 될 때가 아니라."
DavidRR


문제는 세계적인 범위 self === this입니다. 따라서 self로컬 컨텍스트에서 의미가 있으며 패턴을 따르고 있습니다.
programmer5000

답변:


210

이 질문은 jQuery에만 국한된 것이 아니라 일반적으로 JavaScript에만 해당됩니다. 핵심 문제는 임베디드 함수에서 변수를 "채널 화"하는 방법입니다. 이것은 예입니다 :

var abc = 1; // we want to use this variable in embedded functions

function xyz(){
  console.log(abc); // it is available here!
  function qwe(){
    console.log(abc); // it is available here too!
  }
  ...
};

이 기술은 클로저를 사용합니다. 그러나 그것은 작동하지 this않기 때문에this 범위에서 범위로 동적으로 변경 될 수있는 의사 변수 .

// we want to use "this" variable in embedded functions

function xyz(){
  // "this" is different here!
  console.log(this); // not what we wanted!
  function qwe(){
    // "this" is different here too!
    console.log(this); // not what we wanted!
  }
  ...
};

우리는 무엇을 할 수 있습니까? 변수에 할당하고 별명을 통해 사용하십시오.

var abc = this; // we want to use this variable in embedded functions

function xyz(){
  // "this" is different here! --- but we don't care!
  console.log(abc); // now it is the right object!
  function qwe(){
    // "this" is different here too! --- but we don't care!
    console.log(abc); // it is the right object here too!
  }
  ...
};

this이와 관련하여 고유하지 않습니다 arguments. 앨리어싱 (aliasing)으로 같은 방식으로 처리해야하는 다른 의사 변수입니다.


7
"this"를 함수 호출에 바인딩하고 변수 범위를 전달하거나 변수 범위를 가로 지르지 않아야합니다.
michael

10
@ 마이클 왜?
Chris Anderson

@michael 파이프, 맵, 서브 스크립 션 내부에서 하나의 함수에서 호출하고 함수를 호출하지 않을 수 있습니다.이 경우 "this"가 변경되므로 변수 범위가 해결책입니다.
Skander Jenhani

댓글은 8 살입니다. 내 대답은 오늘 매우 달라질 것입니다
마이클

18

예, 이것은 일반적인 표준으로 보입니다. 일부 코더는 자기를 사용하고 다른 코더는 나를 사용합니다. 이벤트와 달리 "실제"객체에 대한 참조로 사용됩니다.

실제로 얻는 데 시간이 조금 걸렸습니다. 처음에는 이상하게 보입니다.

나는 보통 내 객체의 맨 위에서 이것을 수행합니다 (데모 코드는 실례합니다-다른 것보다 더 개념적이며 우수한 코딩 기술에 대한 교훈은 아닙니다) :

function MyObject(){
  var me = this;

  //Events
  Click = onClick; //Allows user to override onClick event with their own

  //Event Handlers
  onClick = function(args){
    me.MyProperty = args; //Reference me, referencing this refers to onClick
    ...
    //Do other stuff
  }
}

12
var functionX = function() {
  var self = this;
  var functionY = function(y) {
    // If we call "this" in here, we get a reference to functionY,
    // but if we call "self" (defined earlier), we get a reference to function X.
  }
}

편집 : 개체 내에서 중첩 함수는 주변 개체가 아닌 전역 창 개체를 사용합니다.


당신은 무엇을 설명하고있는 것처럼 보이지만 var self = this그것은 질문이 묻는 것이 아닙니다 (질문이 문제에 대한 최상의 해결책인지 묻고 있습니다).
Quentin

3
"핵심 문제는 임베디드 함수에서 변수를"채널 화 "하는 방법입니다. 동의 한 답변에이 진술에 동의합니다. 그 외에 "그것"연습에는 아무런 문제가 없습니다. 꽤 일반적입니다. 그래서, "코드가 이상해 보인다"라는 부분에 대한 답으로 나는 그것이 어떻게 작동하는지 설명하기로했다. 나는 "코드가 이상하게 보인다"는 이유는 그것이 어떻게 작동하는지 혼동하기 때문이라고 생각합니다.
serkan

12

ES2015 또는 유형 스크립트 및 ES5를 수행하는 경우 코드에서 화살표 기능을 사용할 수 있으며 해당 오류가 발생하지 않으며 인스턴스에서 원하는 범위를 나타냅니다.

this.name = 'test'
myObject.doSomething(data => {
  console.log(this.name)  // this should print out 'test'
});

5
설명으로 : ES2015에서 화살표 함수 this는 정의 범위에서 캡처 합니다. 일반적인 함수 정의는 그렇게하지 않습니다.
defnull

@defnull 나는 그것이 특별한 것이 아니라고 생각합니다. 함수는 블록 범위를 만듭니다. 따라서 함수 대신 화살표 표기법을 사용하면 범위를 만들 수 없으므로 여전히이 변수 외부를 참조합니다.
Nimeshka Srimal

4

이것에 대한 한 가지 해결책은 모든 콜백을 자바 스크립트로 객체에 바인딩하는 것입니다. bind 메소드 입니다.

명명 된 방법으로이 작업을 수행 할 수 있습니다.

function MyNamedMethod() {
  // You can now call methods on "this" here 
}

doCallBack(MyNamedMethod.bind(this)); 

또는 익명 콜백

doCallBack(function () {
  // You can now call methods on "this" here
}.bind(this));

의지하는 대신 이것들을하는 var self = this것은this 자바 스크립트에서 동작하는지 하고 클로저 참조에 의존하지 않는 .

또한 ES6의 팻 화살표 연산자는 기본적으로 .bind(this)익명 함수를 호출하는 것과 같습니다.

doCallback( () => {
  // You can reference "this" here now
});

개인적으로 나는 .bind (this)가 더 타이핑 하고이 참조를 나 (또는 ​​무엇이든)로 변경 한 다음 대신 사용하면 더 깨끗한 코드를 만든다고 생각합니다. 뚱뚱한 화살은 미래입니다.
davidbuttar

3

jQuery를 사용하지는 않았지만 프로토 타입과 같은 라이브러리에서 함수를 특정 범위에 바인딩 할 수 있습니다. 이를 염두에두고 코드는 다음과 같습니다.

 $('#foobar').ready('click', this.doSomething.bind(this));

bind 메소드는 지정한 범위로 원래 메소드를 호출하는 새 함수를 리턴합니다.


비슷합니다 : $('#foobar').ready('click', this.doSomething.call(this));맞습니까?
Muers

bind이전 브라우저에서는 이 방법이 작동하지 않으므로 $.proxy대신 이 방법을 사용하십시오.
Guffa


1

나는 그것이 실제로 doSomething함수 안에서 무엇을 할 것인지에 달려 있다고 생각합니다 . MyObject이 키워드를 사용하여 속성 에 액세스 하려면 해당 키워드를 사용해야합니다. 그러나 object(MyObject)속성을 사용하여 특별한 작업을 수행하지 않으면 다음 코드 조각도 작동한다고 생각합니다 .

function doSomething(){
  .........
}

$("#foobar").ready('click', function(){

});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.