이 JavaScript 관용구의 기초는 무엇입니까? var self = this?


357

WebKit HTML 5 SQL Storage Notes Demo 의 소스에서 다음을 보았습니다 .

function Note() {
  var self = this;

  var note = document.createElement('div');
  note.className = 'note';
  note.addEventListener('mousedown', function(e) { return self.onMouseDown(e) }, false);
  note.addEventListener('click', function() { return self.onNoteClick() }, false);
  this.note = note;
  // ...
}

저자는 사용 자기 곳곳 (함수 본문) 및 예약 다른 장소에서 (방법 인수리스트에 정의 된 함수의 몸). 무슨 일이야? 이제 한 번 알아 차렸으니 어디서나 볼 수 있을까요?


4
이것은 "어휘 폐쇄"라는 JS 언어 기능입니다.
subZero

2
가능한 복제 : var self = this? .
DavidRR

이것의 개념은 여기에 명시 적으로 설명 scotch.io/@alZami/understanding-this-in-javascript
AL-zami에게

이 답변의 관련 예제 stackoverflow.com/a/20279485/5610569 ( " this콜백 내부 에서 올바른 액세스 방법"질문 )
FluxLemur

답변:


431

alistapart.com 에서이 기사를 참조하십시오 . (Ed : 기사는 원래 링크 된 이후로 업데이트되었습니다)

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

편집 :self 이제는 사용하는 것이 권장 window.self되지 않으며 조심하지 않으면 오류가 발생할 수 있습니다.

변수라고 부르는 것은 특별히 중요하지 않습니다. var that = this;괜찮지 만 이름에 대한 마법은 없습니다.

컨텍스트 내에서 선언 된 함수 (예 : 콜백, 클로저)는 동일한 범위 이상에서 선언 된 변수 / 함수에 액세스 할 수 있습니다.

예를 들어, 간단한 이벤트 콜백 :

function MyConstructor(options) {
  let that = this;

  this.someprop = options.someprop || 'defaultprop';

  document.addEventListener('click', (event) => {
    alert(that.someprop);
  });
}

new MyConstructor({
  someprop: "Hello World"
});


나타납니다 문서 것을 사용으로 변신var that = this;
밥 스테인을

@BobStein 감사합니다. 이에 따라 답변을 업데이트하겠습니다.
Jonathan Fingland

96

현대 브라우저 는 일반 창이나 WebWorker의 전역 객체를 가리키는 전역 변수를self 제공하기 때문에 변수 이름 'self'는 더 이상 이런 식으로 사용해서는 안됩니다 .

혼란과 잠재적 충돌을 피하기 위해 글을 var thiz = this쓰거나 var that = this대신 사용할 수 있습니다 .


43
나는 보통 다음을 사용합니다_this
djheru

6
@djheru +1. " that"(내 두뇌가 결코 익숙해지지 않을 것입니다)보다 훨씬 좋습니다 .
o_o_o--

9
나는 "나": 사용하기 시작
Mopparthy Ravindranath

3
최신 브라우저가 전역 변수 _this, that 또는 me를 제공하기 시작할 때까지.
Beejor

10
이름 selfvariable 로 선언하는 한 이름을 사용하는 데 전혀 문제가 없으며 전역을 가리게됩니다. 물론 잊어 버린 경우 var다른 이름으로도 작동하지 않습니다.
Bergi

34

예, 어디서나 볼 수 있습니다. 종종 that = this;입니다.

self이벤트에서 호출하는 함수 내부에서 어떻게 사용 되는지 확인하십시오 . 사람들은 자신의 컨텍스트를 할 것이다, 그래서 self보류하는 데 사용됩니다 this에 와서 그 Note().

self함수 실행 Note()이 완료된 후에 만 실행할 수 있지만 함수가 여전히 사용할 수 있는 이유 는 내부 함수가 클로저 로 인해 외부 함수의 컨텍스트를 가져 오기 때문 입니다.


12
저에게는 확실한 self의미는 특별한 의미가 없다는 것입니다. 나는 개인적으로 self'self'가 예약어가되기를 기대하기 때문에 종종 나를 혼란스럽게하기 때문에 다른 이름의 var를 사용하는 것을 선호합니다 . 그래서 나는 당신의 대답을 좋아합니다. 그리고 OP의 예에서, 나는 선호 var thisNote = this하거나 비슷합니다.
스티브

@steve는 유지 관리 측면에서 매우 취하기 때문에 일반적 으로이 / 자체 참조를 사용하지 않으려 고 동의했습니다.
mattLummus

28

또한 이디엄 this을 싫어하는 경우 콜백 에서 원본 에 대한 참조를 유지하기위한 대체 프록시 패턴 이 있습니다 var self = this.

함수를 사용하여 지정된 컨텍스트로 호출 할 수있는 것처럼 function.apply또는 function.call, 당신이 래퍼를 작성할 수 반환로 함수를 호출하는 기능 apply이나 call주어진 컨텍스트를 사용하여. proxy이 패턴의 구현에 대해서는 jQuery의 함수를 참조하십시오 . 사용 예는 다음과 같습니다.

var wrappedFunc = $.proxy(this.myFunc, this);

wrappedFunc그런 다음 호출 할 수 this있으며 컨텍스트 버전을 갖습니다 .


10

다른 사람들이 설명했듯이 클로저의var self = this; 코드 가 부모 범위를 다시 참조하도록 허용합니다 .

그러나 현재 2018 년이며 ES6는 모든 주요 웹 브라우저에서 널리 지원됩니다. var self = this;관용구는 예전과 같이 확실히 필요는 없다.

이제 화살표 함수를var self = this; 사용 하여 피할 수 있습니다 .

우리가 사용한 경우 var self = this:

function test() {
    var self = this;
    this.hello = "world";
    document.getElementById("test_btn").addEventListener("click", function() {
        console.log(self.hello); // logs "world"
    });
};

이제 화살표 기능을 사용할 수 없습니다 var self = this:

function test() {
    this.hello = "world";
    document.getElementById("test_btn").addEventListener("click", () => {
        console.log(this.hello); // logs "world"
    });
};

화살표 함수에는 고유 한 기능이 없으며 this단순히 포함 범위를 가정합니다.


또는 – 충격, 공포! – 실제 관련 사항을 함수 (클로즈)의 인수로 전달하지 않겠습니까? 대체 왜 범위를 벗어난 상태를 참조하고 있습니까? 왜 이런 프로그래밍을하는 사람이 있습니까? 이를 수행 할 실제 이유 는 없습니다 . 대신에 .addEventListender("click", (x) => { console.log(x); });당신은 방법과 이유를 매우 명확하게 설명했으며 화살표 기능을 사용하는 것이 더 합리적이지만 여전히 끔찍하고 게으르고 지저분한 프로그래밍입니다.
Benjamin R

2
JavaScript에서는 부모 범위를 다시 참조하는 것이 매우 일반적이며 필요합니다. 언어의 기본 부분입니다. 이벤트 처리기에서 인수로 부모 범위를 전달하라는 제안은 실제로 불가능합니다. 또한 ES6에서 화살표 함수는 어휘 범위를 사용합니다. '이것은 현재 주변 범위를 나타내며 더 이상은 아닙니다. "범위를 벗어난 참조"또는 이와 유사한 것은 아닙니다.
엘리엇 B.

9

변수는 메소드에 정의 된 인라인 함수로 캡처됩니다. this함수에서 다른 객체를 참조합니다. 이런 식으로 함수를 this외부 범위 의 참조로 유지할 수 있습니다 .


9

자바 스크립트 문제입니다. 함수는 객체의 속성 인 경우, 더 적절하게, 메소드 호출 객체를 의미한다. 이벤트 핸들러의 예에서 포함 오브젝트는 이벤트를 트리거 한 요소입니다. 표준 함수가 호출 될 때, 전역 객체를 참조합니다. 당신이 당신의 예에서와 같이 중첩 된 기능이있을 때, 모두에서 외부 함수의 컨텍스트에 관련되지 않습니다. 개발자의 변형을 사용할 수 있도록 내부 기능은 포함하는 기능을 가진 공유 범위를 할 var that = this보존하기 위해 그들이 내부 기능에 필요합니다.


5

실제로 self는 window ( window.self)에 var self = 'something'대한 참조이므로 window 객체에 self가 있기 때문에 자신에 대한 window reference를 재정의 한다고 말할 때 .

대부분의 개발자들이 선호하는 이유입니다 var that = this이상var self = this;

어쨌든; var that = this;모범 사례와 일치하지 않습니다 ... 다른 개발자가 나중에 코드를 수정 / 수정한다고 가정하면 개발자 커뮤니티와 관련하여 가장 일반적인 프로그래밍 표준을 사용해야합니다

따라서 var oldThis/ var oThis/ etc 와 같은 것을 사용해야 범위에서 명확하게 // // .. 그다지 많지 않지만 몇 초와 적은 두뇌주기를 절약 할 수 있습니다.


2
@prior 나는 마지막 단락까지 의미가 있다고 생각합니다.
miphe

0

위에서 여러 번 언급했듯이 'self'는 단순히 함수에 들어가기 전에 'this'에 대한 참조를 유지하는 데 사용됩니다. 함수에서 'this'는 다른 것을 의미합니다.


@JohnPaul ...이 수행 답변을 제공합니다. 정답이 아닐 수도 있지만 어떻게 "이것이 익숙해 졌는가?"는 "그가 왜 그렇게 했는가"에 대한 대답이 아닙니까?
GreenAsJade

-1
function Person(firstname, lastname) {
  this.firstname = firstname;

  this.lastname = lastname;
  this.getfullname = function () {
    return `${this.firstname}   ${this.lastname}`;
  };

  let that = this;
  this.sayHi = function() {
    console.log(`i am this , ${this.firstname}`);
    console.log(`i am that , ${that.firstname}`);
  };
}

let thisss = new Person('thatbetty', 'thatzhao');

let thatt = {firstname: 'thisbetty', lastname: 'thiszhao'};

thisss.sayHi.call (thatt);


1
특수한 작업에 대한 설명을 코드와 함께 추가해야합니다.
Farhana
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.