“this”키워드는 어떻게 작동합니까?


1309

나는 무엇에 대한 명확한 설명이없는 것으로 나타났습니다 this키워드가 키워드가 스택 오버플로 사이트의 JavaScript에서 올바르게 (잘못) 사용되는 방법에 .

나는 그것에 대해 매우 이상한 행동을 목격했으며 왜 그런 일이 일어 났는지 이해하지 못했습니다.

어떻게 this작동하고 언제 사용해야합니까?





1

2
this키워드에 대한 흥미로운 설명 : rainsoft.io/gentle-explanation-of-this-in-java-script
Dmitri Pavlutin

답변:


1350

Mike West 의 기사 Scope in JavaScript ( mirror )를 먼저 읽는 것이 좋습니다 . 그것은 개념에 대한 훌륭하고 친근한 소개입니다.thisJavaScript 과 범위 체인에 입니다.

에 익숙해지기 시작 this하면 규칙은 실제로 매우 간단합니다. 인 ECMAScript 5.1 표준 을 정의 this:

§11.1.1this 키워드

this현재 실행 컨텍스트의 ThisBinding의 값 키워드 평가됩니다

ThisBinding은 객체에 대한 참조를 보유하는 특수 CPU 레지스터와 같이 JavaScript 코드를 평가할 때 JavaScript 인터프리터가 유지 관리하는 것입니다. 인터프리터는 세 가지 경우 중 하나에서 실행 컨텍스트를 설정할 때마다 ThisBinding을 업데이트합니다.

1. 초기 전역 실행 컨텍스트

최상위 레벨에서 평가되는 JavaScript 코드의 경우입니다 (예 <script>:

<script>
  alert("I'm evaluated in the initial global execution context!");

  setTimeout(function () {
      alert("I'm NOT evaluated in the initial global execution context.");
  }, 1);
</script>

초기 전역 실행 컨텍스트에서 코드를 평가할 때 ThisBinding은 전역 개체 window( §10.4.1.1 )로 설정됩니다.

평가 코드 입력

  • eval() ThisBinding 에 대한 직접 호출 은 변경되지 않습니다. 호출 실행 컨텍스트의 ThisBinding과 동일한 값입니다 ( §10.4.2 (2) (a)).

  • eval()
    ThisBinding을 직접 호출하지 않으면 초기 전역 실행 컨텍스트 ( §10.4.2 (1)) 에서 실행하는 것처럼 이 바인딩이 전역 개체 설정됩니다 .

§15.1.2.1.1은 직접 호출이 무엇인지 정의합니다 eval(). 기본적으로 eval(...)직접 전화를하는 반면에 (0, eval)(...)또는 var indirectEval = eval; indirectEval(...);에 대한 간접 전화를하는 것 eval()입니다. JavaScript에서 (1, eval) ( 'this') vs eval ( 'this')에 대한 chuckj의 답변 을 참조하십시오 . Dmitry Soshnikov의 ECMA-262-5에 대해 자세히 설명합니다. 2 장. 엄격한 모드. 간접 eval()통화를 사용할 수 있습니다 .

기능 코드 입력

이것은 함수를 호출 할 때 발생합니다. in obj.myMethod()또는 equivalent 과 같은 객체에서 함수가 호출되면 obj["myMethod"]()ThisBinding이 객체로 설정됩니다 ( obj예 : §13.2.1 ). 대부분의 경우이 바인딩은 전역 객체 ( §10.4.3 )로 설정됩니다 .

"대부분의 다른 경우"를 작성하는 이유는 인수 목록에 ThisBinding을 지정할 수있는 ECMAScript 5 내장 함수가 8 개 있기 때문입니다. 이러한 특수 함수는 소위 thisArg호출되어 함수를 호출 할 때 ThisBinding이됩니다 ( §10.4.3 ).

이러한 특수 내장 기능은 다음과 같습니다.

  • Function.prototype.apply( thisArg, argArray )
  • Function.prototype.call( thisArg [ , arg1 [ , arg2, ... ] ] )
  • Function.prototype.bind( thisArg [ , arg1 [ , arg2, ... ] ] )
  • Array.prototype.every( callbackfn [ , thisArg ] )
  • Array.prototype.some( callbackfn [ , thisArg ] )
  • Array.prototype.forEach( callbackfn [ , thisArg ] )
  • Array.prototype.map( callbackfn [ , thisArg ] )
  • Array.prototype.filter( callbackfn [ , thisArg ] )

Function.prototype함수 의 경우 함수 객체에서 호출되지만 ThisBinding을 함수 객체로 설정하지 않고 ThisBinding이thisArg .

의 경우에 Array.prototype기능이 지정된 callbackfnThisBinding로 설정 실행 컨텍스트에서 호출 thisArg공급하는 경우; 그렇지 않으면 전역 객체에.

이것들은 일반 JavaScript의 규칙입니다. JavaScript 라이브러리 (예 : jQuery)를 사용하기 시작하면 특정 라이브러리 함수가의 값을 조작 할 수 있습니다 this. JavaScript 라이브러리의 개발자는 가장 일반적인 사용 사례를 지원하는 경향이 있기 때문에이 작업을 수행하며 일반적으로 라이브러리 사용자는이 동작이 더 편리하다는 것을 알게됩니다. this라이브러리 함수를 참조하는 콜백 함수를 전달할 this때 함수가 호출 될 때의 값에 대한 보증은 설명서를 참조해야합니다 .

JavaScript 라이브러리가의 값을 조작하는 방법에 대해 궁금한 경우 this라이브러리는 단순히을 허용하는 내장 JavaScript 함수 중 하나를 사용합니다 thisArg. 콜백 함수를 사용하여 자신의 함수를 작성할 수도 있습니다 thisArg.

function doWork(callbackfn, thisArg) {
    //...
    if (callbackfn != null) callbackfn.call(thisArg);
}

내가 아직 언급하지 않은 특별한 경우가 있습니다. new연산자 를 통해 새 객체를 구성 할 때 JavaScript 인터프리터는 비어 있는 새 객체를 만들고 내부 속성을 설정 한 다음 새 객체에서 생성자 함수를 호출합니다. 따라서 생성자 컨텍스트에서 함수가 호출되면 그 값은 this인터프리터가 만든 새 객체입니다.

function MyType() {
    this.someData = "a string";
}

var instance = new MyType();
// Kind of like the following, but there are more steps involved:
// var instance = {};
// MyType.call(instance);

화살표 기능

ECMA6에 도입 된 화살표 기능 은의 범위를 변경합니다 this. 기존의 표준 질문 인 화살표 함수 대 함수 선언 / 표현을 참조하십시오 . 자세한 내용은. 그러나 간단히 말하면 :

화살표 함수에는 자체 this.... 바인딩 이 없습니다 . 대신, 이러한 식별자는 다른 변수와 같이 어휘 범위에서 분석됩니다. 즉, 화살표 함수 내부 에서 화살표 함수가 정의 된 환경의 this값을 참조 this합니다.

재미를 위해 몇 가지 예를 통해 이해를 테스트하십시오.

답을 나타내려면 밝은 회색 상자 위로 마우스를 이동하십시오.

  1. 의 가치는 무엇입니까 this표시된 줄 얼마입니까? 왜?

    window — 표시된 행은 초기 전역 실행 컨텍스트에서 평가됩니다.

    if (true) {
        // What is `this` here?
    }
  2. this때 표시 줄에 값은 무엇입니까obj.staticFunction()실행될 얼마입니까? 왜?

    obj — 객체에서 함수를 호출 할 때 ThisBinding이 객체로 설정됩니다.

    var obj = {
        someData: "a string"
    };
    
    function myFun() {
        return this // What is `this` here?
    }
    
    obj.staticFunction = myFun;
    
    console.log("this is window:", obj.staticFunction() == window);
    console.log("this is obj:", obj.staticFunction() == obj);
      

  3. this표시된 줄 의 값은 얼마입니까? 왜?

    window

    이 예제에서 JavaScript 인터프리터는 함수 코드를 입력하지만 myFunobj.myMethod 오브젝트에서 / 가 호출되지 ThisBinding이로 설정됩니다 window.

    이것은 메소드 ( obj.myMethod)에 액세스 하여 바인딩 된 메소드 객체를 만드는 Python과 다릅니다 .

    var obj = {
        myMethod: function () {
            return this; // What is `this` here?
        }
    };
    var myFun = obj.myMethod;
    console.log("this is window:", myFun() == window);
    console.log("this is obj:", myFun() == obj);
      

  4. this표시된 줄 의 값은 얼마입니까? 왜?

    window

    이건 까다로웠다. 평가 코드를 평가할 때는 this입니다 obj. 그러나 평가 코드에서는 myFun개체에서 호출되지 않으므로 ThisBinding이 window호출로 설정됩니다 .

    function myFun() {
        return this; // What is `this` here?
    }
    var obj = {
        myMethod: function () {
            eval("myFun()");
        }
    };
  5. this표시된 줄 의 값은 얼마입니까? 왜?

    obj

    이 라인 myFun.call(obj);은 특수 내장 함수를 호출 하며, 첫 번째 인수로 Function.prototype.call()허용 thisArg됩니다.

    function myFun() {
        return this; // What is `this` here?
    }
    var obj = {
        someData: "a string"
    };
    console.log("this is window:", myFun.call(obj) == window);
    console.log("this is obj:", myFun.call(obj) == obj);
      


6
@Ali : ECMAScript Standard, ECMA-262의 5.1 판 섹션에 대한 참조 입니다. 원하는 경우 기술 세부 사항에 대한 표준을 읽을 수 있도록 제공합니다.
Daniel Trebbien

1
@supertonsky가 # 2에 대해 맞다고 생각합니다. 만약 myFun ()이 전역 범위에서 호출되고 객체의 메소드가 아니라면 "this"가 전역 객체가 될 것이므로 질문의 표현이 중요합니다. btw- 마우스 오버를 사용하여 이와 같은 답변을 얻는 아이디어가 정말 좋습니다.
user655489

2
그러나, jsfiddle.net/H4LYm/2는 보여줍니다 setTimeout예는있다 thiswindow(global).
케빈 메러디스

2
파이썬 하나에서 오는 내가 3 예에 충돌 할 때 내가 가진 불만의 수준을 상상 .. SMH
마리우스 Mucenicu

1
변경 사항이 용어에 불과하더라도 ES2020 현실을 반영하도록이 답변을 업데이트해야합니다.
벤 애스턴

156

this다른 자바 스크립트의 키워드 동작합니다 다른 언어에 비해. 객체 지향 언어에서 this키워드는 클래스의 현재 인스턴스를 나타냅니다. JavaScript에서의 값 this은 함수의 호출 컨텍스트에 의해 결정됩니다 (context.function() ) .

1. 글로벌 맥락에서 사용될 때

this글로벌 컨텍스트에서 사용하면 글로벌 오브젝트에 바인딩됩니다 ( window브라우저에서)

document.write(this);  //[object Window]

this전역 컨텍스트에 정의 된 함수 내부에서 사용 하는 this경우 함수가 실제로 전역 컨텍스트의 메서드로 만들어지기 때문에 여전히 전역 개체에 바인딩됩니다.

function f1()
{
   return this;
}
document.write(f1());  //[object Window]

f1는 전역 객체의 방법입니다. 따라서 window다음과 같이 객체에서 호출 할 수도 있습니다.

function f()
{
    return this;
}

document.write(window.f()); //[object Window]

2. 객체 메소드 내부에서 사용될 때

this객체 메소드 내에서 키워드 를 사용 this하면 "바로"둘러싸는 객체에 바인딩됩니다.

var obj = {
    name: "obj",
    f: function () {
        return this + ":" + this.name;
    }
};
document.write(obj.f());  //[object Object]:obj

위의 단어를 즉시 큰 따옴표로 묶었습니다. 객체를 다른 객체 안에 중첩 this하면 바로 부모에 바인딩됩니다.

var obj = {
    name: "obj1",
    nestedobj: {
        name:"nestedobj",
        f: function () {
            return this + ":" + this.name;
        }
    }            
}

document.write(obj.nestedobj.f()); //[object Object]:nestedobj

메소드를 객체에 명시 적으로 함수를 추가하더라도 여전히 위의 규칙을 따르며 this이는 바로 상위 부모 객체를 가리 킵니다.

var obj1 = {
    name: "obj1",
}

function returnName() {
    return this + ":" + this.name;
}

obj1.f = returnName; //add method to object
document.write(obj1.f()); //[object Object]:obj1

3. 문맥없는 기능을 호출 할 때

this컨텍스트없이 호출 된 내부 함수 를 사용하는 경우 (예 : 오브젝트가 아닌) 글로벌 window함수 (브라우저에서) (함수가 오브젝트 내부에 정의 된 경우에도)에 바인딩됩니다 .

var context = "global";

var obj = {  
    context: "object",
    method: function () {                  
        function f() {
            var context = "function";
            return this + ":" +this.context; 
        };
        return f(); //invoked without context
    }
};

document.write(obj.method()); //[object Window]:global 

기능으로 모든 것을 시도

함수로 위의 포인트를 시험해 볼 수도 있습니다. 그러나 약간의 차이가 있습니다.

  • 위에서 객체 리터럴 표기법을 사용하여 객체에 멤버를 추가했습니다. 를 사용하여 함수에 멤버를 추가 할 수 있습니다 this. 그들을 지정합니다.
  • 객체 리터럴 표기법은 즉시 사용할 수있는 객체 인스턴스를 만듭니다. 함수를 사용하면 먼저 new연산자 를 사용하여 인스턴스를 만들어야합니다 .
  • 또한 객체 리터럴 방식에서는 점 연산자를 사용하여 이미 정의 된 객체에 멤버를 명시 적으로 추가 할 수 있습니다. 이것은 특정 인스턴스에만 추가됩니다. 그러나 함수 프로토 타입에 변수를 추가하여 함수의 모든 인스턴스에 반영되도록했습니다.

아래에서는 Object this이상에서 수행 한 모든 작업을 시도 했지만 먼저 직접 객체를 작성하는 대신 함수를 작성했습니다.

/********************************************************************* 
  1. When you add variable to the function using this keyword, it 
     gets added to the function prototype, thus allowing all function 
     instances to have their own copy of the variables added.
*********************************************************************/
function functionDef()
{
    this.name = "ObjDefinition";
    this.getName = function(){                
        return this+":"+this.name;
    }
}        

obj1 = new functionDef();
document.write(obj1.getName() + "<br />"); //[object Object]:ObjDefinition   

/********************************************************************* 
   2. Members explicitly added to the function protorype also behave 
      as above: all function instances have their own copy of the 
      variable added.
*********************************************************************/
functionDef.prototype.version = 1;
functionDef.prototype.getVersion = function(){
    return "v"+this.version; //see how this.version refers to the
                             //version variable added through 
                             //prototype
}
document.write(obj1.getVersion() + "<br />"); //v1

/********************************************************************* 
   3. Illustrating that the function variables added by both above 
      ways have their own copies across function instances
*********************************************************************/
functionDef.prototype.incrementVersion = function(){
    this.version = this.version + 1;
}
var obj2 = new functionDef();
document.write(obj2.getVersion() + "<br />"); //v1

obj2.incrementVersion();      //incrementing version in obj2
                              //does not affect obj1 version

document.write(obj2.getVersion() + "<br />"); //v2
document.write(obj1.getVersion() + "<br />"); //v1

/********************************************************************* 
   4. `this` keyword refers to the immediate parent object. If you 
       nest the object through function prototype, then `this` inside 
       object refers to the nested object not the function instance
*********************************************************************/
functionDef.prototype.nestedObj = { name: 'nestedObj', 
                                    getName1 : function(){
                                        return this+":"+this.name;
                                    }                            
                                  };

document.write(obj2.nestedObj.getName1() + "<br />"); //[object Object]:nestedObj

/********************************************************************* 
   5. If the method is on an object's prototype chain, `this` refers 
      to the object the method was called on, as if the method was on 
      the object.
*********************************************************************/
var ProtoObj = { fun: function () { return this.a } };
var obj3 = Object.create(ProtoObj); //creating an object setting ProtoObj
                                    //as its prototype
obj3.a = 999;                       //adding instance member to obj3
document.write(obj3.fun()+"<br />");//999
                                    //calling obj3.fun() makes 
                                    //ProtoObj.fun() to access obj3.a as 
                                    //if fun() is defined on obj3

4. 생성자 함수 안에서 사용될 때 .

함수가 생성자로 사용되면 (즉 new, 키워드 와 함께 호출 될 때 ) this함수 본문 내부는 생성중인 새 객체를 가리 킵니다.

var myname = "global context";
function SimpleFun()
{
    this.myname = "simple function";
}

var obj1 = new SimpleFun(); //adds myname to obj1
//1. `new` causes `this` inside the SimpleFun() to point to the
//   object being constructed thus adding any member
//   created inside SimipleFun() using this.membername to the
//   object being constructed
//2. And by default `new` makes function to return newly 
//   constructed object if no explicit return value is specified

document.write(obj1.myname); //simple function

5. 프로토 타입 체인에 정의 된 함수 내부에서 사용될 때

메소드가 오브젝트의 프로토 타입 체인에있는 경우 해당 메소드 this내부에서 메소드가 오브젝트에 정의 된 것처럼 메소드가 호출 된 오브젝트를 참조합니다.

var ProtoObj = {
    fun: function () {
        return this.a;
    }
};
//Object.create() creates object with ProtoObj as its
//prototype and assigns it to obj3, thus making fun() 
//to be the method on its prototype chain

var obj3 = Object.create(ProtoObj);
obj3.a = 999;
document.write(obj3.fun()); //999

//Notice that fun() is defined on obj3's prototype but 
//`this.a` inside fun() retrieves obj3.a   

6. 내부 call (), apply () 및 bind () 함수

  • 이 모든 방법은에 정의되어 Function.prototype있습니다.
  • 이 메소드는 함수를 한 번 작성하고 다른 컨텍스트에서 호출 할 수있게합니다. 즉, this함수가 실행되는 동안 사용될 값을 지정할 수 있습니다 . 또한 호출 될 때 원래 함수로 전달되는 매개 변수를 사용합니다.
  • fun.apply(obj1 [, argsArray])inside obj1의 값으로 설정 하고 인수로 전달되는 요소를 호출합니다 .thisfun()fun()argsArray
  • fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])- 내부 obj1값으로 설정 하고 인수로 전달하는 호출 .thisfun()fun()arg1, arg2, arg3, ...
  • fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])- 기능에 대한 참조를 반환 funthis내부에 결합 재미 obj1와의 매개 변수에 fun지정된 매개 변수에 바인딩을 arg1, arg2, arg3,....
  • 지금까지 사이의 차이 apply, call그리고 bind명확하게해야합니다. apply배열과 같은 객체, 즉 숫자 length속성과 해당하는 음이 아닌 정수 속성을 가진 객체로 작동하는 인수를 지정할 수 있습니다. 반면 call함수에 인수를 직접 지정할 수 있습니다. 모두 applycall즉시 지정된 컨텍스트에서 지정된 인수와 함께 함수를 호출합니다. 반면 bind에, 지정된 this값과 인수에 바인딩 된 함수를 반환합니다 . 이 반환 된 함수에 대한 참조를 변수에 지정하여 나중에 참조 할 수 있습니다.
function add(inc1, inc2)
{
    return this.a + inc1 + inc2;
}

var o = { a : 4 };
document.write(add.call(o, 5, 6)+"<br />"); //15
      //above add.call(o,5,6) sets `this` inside
      //add() to `o` and calls add() resulting:
      // this.a + inc1 + inc2 = 
      // `o.a` i.e. 4 + 5 + 6 = 15
document.write(add.apply(o, [5, 6]) + "<br />"); //15
      // `o.a` i.e. 4 + 5 + 6 = 15

var g = add.bind(o, 5, 6);       //g: `o.a` i.e. 4 + 5 + 6
document.write(g()+"<br />");    //15

var h = add.bind(o, 5);          //h: `o.a` i.e. 4 + 5 + ?
document.write(h(6) + "<br />"); //15
      // 4 + 5 + 6 = 15
document.write(h() + "<br />");  //NaN
      //no parameter is passed to h()
      //thus inc2 inside add() is `undefined`
      //4 + 5 + undefined = NaN</code>

7. this내부 이벤트 핸들러

  • 함수를 요소의 이벤트 핸들러에 직접 지정하는 경우 this이벤트 처리 함수 내부 에서 직접 사용 하는 것은 해당 요소를 나타냅니다. 이러한 직접 기능 할당은 addeventListener방법을 사용 하거나와 같은 전통적인 이벤트 등록 방법을 통해 수행 할 수 있습니다 onclick.
  • 마찬가지로 요소 this의 이벤트 속성 (예 :) 내에서 직접 사용 하는 경우 <button onclick="...this..." >요소를 나타냅니다.
  • 그러나 this이벤트 처리 함수 또는 이벤트 속성 내에서 호출 된 다른 함수를 통해 간접적으로 사용 하면 전역 객체로 해석됩니다 window.
  • Microsoft의 이벤트 등록 모델 방법을 사용하여 함수를 이벤트 핸들러에 첨부하면 위와 동일한 동작이 수행됩니다 attachEvent. 함수를 이벤트 핸들러에 할당하는 대신 (요소의 함수 메소드를 작성하는) 대신 이벤트에서 함수를 호출합니다 (글로벌 컨텍스트에서 효과적으로 호출).

JSFiddle 에서 더 잘 시도하는 것이 좋습니다 .

<script> 
    function clickedMe() {
       alert(this + " : " + this.tagName + " : " + this.id);
    } 
    document.getElementById("button1").addEventListener("click", clickedMe, false);
    document.getElementById("button2").onclick = clickedMe;
    document.getElementById("button5").attachEvent('onclick', clickedMe);   
</script>

<h3>Using `this` "directly" inside event handler or event property</h3>
<button id="button1">click() "assigned" using addEventListner() </button><br />
<button id="button2">click() "assigned" using click() </button><br />
<button id="button3" onclick="alert(this+ ' : ' + this.tagName + ' : ' + this.id);">used `this` directly in click event property</button>

<h3>Using `this` "indirectly" inside event handler or event property</h3>
<button onclick="alert((function(){return this + ' : ' + this.tagName + ' : ' + this.id;})());">`this` used indirectly, inside function <br /> defined & called inside event property</button><br />

<button id="button4" onclick="clickedMe()">`this` used indirectly, inside function <br /> called inside event property</button> <br />

IE only: <button id="button5">click() "attached" using attachEvent() </button>

8. thisES6 화살표 기능

화살표 함수에서 this공통 변수처럼 동작합니다. 어휘 범위에서 상속됩니다. 함수의 this화살표 함수가 정의되고, 상기 화살표의 기능을 할 것이다 this.

따라서 다음과 같은 동작입니다.

(function(){}).bind(this)

다음 코드를 참조하십시오.

const globalArrowFunction = () => {
  return this;
};

console.log(globalArrowFunction()); //window

const contextObject = {
  method1: () => {return this},
  method2: function(){
    return () => {return this};
  }
};

console.log(contextObject.method1()); //window

const contextLessFunction = contextObject.method1;

console.log(contextLessFunction()); //window

console.log(contextObject.method2()()) //contextObject

const innerArrowFunction = contextObject.method2();

console.log(innerArrowFunction()); //contextObject 

"글로벌 컨텍스트에 정의 된 함수 내에서 이것을 사용할 때, 함수가 실제로 글로벌 컨텍스트의 메소드로 만들어지기 때문에 여전히 글로벌 오브젝트에 바인드됩니다." 부정확하다. 이것은 함수 가 정의 된 위치가 아니라 함수가 호출되는 방식 또는 bind 에 의해 설정됩니다. 기본 참조 ( "컨텍스트")없이 함수를 호출하면 기본값으로 전역 객체 또는 엄격 모드에서 정의되지 않은 상태로 유지됩니다.
RobG

@RobG 흠이 될 수 있지만, 나는 발견 MDN에이 : 이 경우,의 값은 this호출에 의해 설정되어 있지 않습니다. 코드가 엄격 모드가 아니기 때문에 값은 this항상 객체 여야하므로 기본값은 전역 객체입니다. 그리고 실제로 우리가 직접 call을 할 수 있다고 생각한 이유 는 이미 객체에 첨부 window.f1()되어 있다는 것을 의미 합니다. 내가 잘못하고 있습니까? f1()window
Mahesha999 2016 년

나는 당신이의 설정 연결에 (아마도 명확하지) 주석 된 그것을 일종의라고의 인 것처럼, "함수가 실제로 국제적인 맥락의 방법을 만들어"로 window.fn그것을하지 않은. 에는 기본 참조 때문이 아니라 함수가 정의 된 곳으로, 호출에 사용하지 않았기 때문에 전역 객체에 대한 기본값은 (그래서 이것은 여전히 함수가 호출 된 방법에 의해 설정된다). 를 사용하여 명시 적으로 호출하면 windowwindow.fn 로 설정 하는 것 입니다. 같은 결과, 다른 방식으로 진행됩니다. :-)
RobG

"위에 내가 바로 그 단어를 썼다 ..." 오류를 수정하기 위해이를 수정할 수 있습니까? 그것은 대답의 의미론처럼 보이므로 잘못된 것을 배우는 것에 대한 두려움으로 오류가 수정 될 때까지 계속 읽을 수 없습니다.
TylerH

@TylerH는 브라우저에서이 페이지에서 Ctrl + F를 사용하여 문자열 "즉시"(큰 따옴표 포함)를 찾습니다. 만약 내가 잘못 이해한다면 거기에 있다고 생각합니다
Mahesha999

64

자바 스크립트 this

간단한 함수 호출

다음 기능을 고려하십시오.

function foo() {
    console.log("bar");
    console.log(this);
}
foo(); // calling the function

우리는 이것을 일반 모드에서 실행하고 있습니다. 즉, 엄격 모드는 사용되지 않습니다.

브라우저에서 실행할 때의 값 this은로 기록됩니다 window. 이 때문입니다window 웹 브라우저 범위의 전역 변수 입니다.

node.js와 같은 환경에서 동일한 코드를 실행하면 this 앱의 전역 변수를 참조합니다.

이제 "use strict";함수 선언의 시작 부분에 명령문 을 추가하여 엄격 모드에서 이것을 실행하면 this더 이상 환경 중 하나에서 전역 변수를 참조하지 않습니다. 엄격 모드에서 혼동을 피하기 위해 수행됩니다. this이 경우에는 그냥 로그undefined 입니다. 그것이 정의 된 것이 아니기 때문입니다.

다음과 같은 경우에 우리는 this 있습니다.

객체에서 함수 호출

이를 수행하는 다른 방법이 있습니다. forEachand와 같은 Javascript에서 원시 메소드를 호출 한 경우, 해당 경우 변수가 해당 함수를 호출 한 것을 참조한다는 slice것을 이미 알고 있어야 합니다 (javascript에서는 거의 모든 것이 s 및 s를 포함하여 ). 예를 들어 다음 코드를 사용하십시오.thisObjectObjectArrayFunction

var myObj = {key: "Obj"};
myObj.logThis = function () {
    // I am a method
    console.log(this);
}
myObj.logThis(); // myObj is logged

Object에 속성이 포함 된 속성이 포함되어 있으면 속성을 Function메소드라고합니다. 이 메소드는 호출 될 때 항상 연관된 this변수로 설정됩니다 Object. 이는 엄격 및 비 엄격 모드 모두에 해당됩니다.

메소드가 다른 변수에 저장되거나 복사되는 경우 참조 this는 더 이상 새 변수에 유지되지 않습니다. 예를 들면 다음과 같습니다.

// continuing with the previous code snippet

var myVar = myObj.logThis;
myVar();
// logs either of window/global/undefined based on mode of operation

보다 일반적으로 실용적인 시나리오를 고려하십시오.

var el = document.getElementById('idOfEl');
el.addEventListener('click', function() { console.log(this) });
// the function called by addEventListener contains this as the reference to the element
// so clicking on our element would log that element itself

new키워드

Javascript에서 생성자 함수를 고려하십시오.

function Person (name) {
    this.name = name;
    this.sayHello = function () {
        console.log ("Hello", this);
    }
}

var awal = new Person("Awal");
awal.sayHello();
// In `awal.sayHello`, `this` contains the reference to the variable `awal`

어떻게 작동합니까? new키워드를 사용할 때 어떤 일이 발생하는지 봅시다 .

  1. new키워드로 함수를 호출하면 Object의 유형 이 즉시 초기화 Person됩니다.
  2. 이 생성자는 Object생성자를로 설정했습니다 Person. 또한 typeof awal반환 Object만합니다.
  3. 이 새로운 것에 Object는의 프로토 타입이 할당됩니다 Person.prototype. Person이는를 Person포함하여의 모든 인스턴스 에서 프로토 타입의 모든 메소드 또는 속성을 사용할 수 있음을 의미합니다 awal.
  4. 함수 Person자체가 이제 호출됩니다. this새롭게 구성된 객체에 대한 참조 awal입니다.

아주 간단합니까?

공식 ECMAScript 사양에는 이러한 유형의 기능이 실제 constructor기능 이라고 명시되어 있지 않습니다. 그것들은 단지 정상적인 기능이며 new모든 기능에서 사용될 수 있습니다. 단지 우리가 그것들을 그대로 사용하는 것 뿐이므로, 그것들을 그렇게 만 부릅니다.

함수에서 함수 호출 : callapply

그래서 그래, 이후 function의도 있습니다Objects (그리고 실제로 Javascript의 첫 번째 클래스 변수이기 때문에) 함수조차도 함수 자체가 있습니다.

모든 기능은 세계에서 상속 Function, 그 많은 방법이 있습니다 callapply, 둘 다의 값을 조작하는 데 사용할 수있는 this가 호출되는 함수를.

function foo () { console.log (this, arguments); }
var thisArg = {myObj: "is cool"};
foo.call(thisArg, 1, 2, 3);

사용하는 일반적인 예입니다 call. 기본적으로 첫 번째 매개 변수 this를 사용하고 함수 foo에 대한 참조로 설정 thisArg합니다. 전달 된 다른 모든 매개 변수는 인수로 call함수에 전달됩니다 foo.
따라서 위의 코드는 {myObj: "is cool"}, [1, 2, 3]콘솔에 로그인 합니다. 가치를 바꾸는 아주 좋은 방법this모든 함수에서 입니다.

applycall두 개의 매개 변수 만 사용한다는 점 과 거의 동일 thisArg합니다. 함수에 전달할 인수가 포함 된 배열입니다. 따라서 위의 call호출은 다음 apply과 같이 번역 될 수 있습니다 .

foo.apply(thisArg, [1,2,3])

그 주 callapply의 값을 대체 할 수 있습니다this 우리 번째 탄환에서 설명한 도트 메소드 호출에 의해 설정한다. 충분히 간단하다 :)

발표 .... bind !

bind의 형제 callapply. 또한 FunctionJavascript 의 전역 생성자에서 모든 함수에 의해 상속되는 메소드 입니다. 차이 bindcall/ apply그 모두 인 callapply것 실제로 기능을 호출한다. bind반면에는 thisArgarguments사전 설정을 사용하여 새 함수를 반환합니다 . 이것을 더 잘 이해하기 위해 예를 들어 봅시다.

function foo (a, b) {
    console.log (this, arguments);
}
var thisArg = {myObj: "even more cool now"};
var bound = foo.bind(thisArg, 1, 2);
console.log (typeof bound); // logs `function`
console.log (bound);
/* logs `function () { native code }` */

bound(); // calling the function returned by `.bind`
// logs `{myObj: "even more cool now"}, [1, 2]`

세 가지의 차이점을 보시겠습니까? 미묘하지만 다르게 사용됩니다. 같이 call하고 apply, bind또한 값 오버 탈 것 this도트 메소드 호출에 의해 설정합니다.

또한이 세 기능 중 어느 것도 원래 기능을 변경하지 않습니다. call그리고 apply갓 건설 기능에서 값을 반환하면서bind 준비가 갓 건설 기능 자체가, 호출 할 돌아갑니다.

추가 물건, 이것을 복사

때로는 this범위, 특히 중첩 범위에 따라 변경 되는 사실이 마음에 들지 않습니다 . 다음 예를 살펴보십시오.

var myObj = {
    hello: function () {
        return "world"
        },
    myMethod: function () {
        // copy this, variable names are case-sensitive
        var that = this;
        // callbacks ftw \o/
        foo.bar("args", function () {
            // I want to call `hello` here
            this.hello(); // error
            // but `this` references to `foo` damn!
            // oh wait we have a backup \o/
            that.hello(); // "world"
        });
    }
  };

위의 코드 this에서 중첩 범위로 값이 변경 되었음을 알지만 this원래 범위에서 값을 원했습니다 . 우리가 '복사'그래서 thisthat사용 된 대신의 복사this . 영리한가?

인덱스:

  1. 개최 내용 this기본적으로 됩니까?
  2. 객체 점 표기법을 사용하여 함수를 함수로 호출하면 어떻게됩니까?
  3. 우리가 new키워드를 어떻게 되나요?
  4. 우리는 어떻게 조작 할 thiscallapply?
  5. 사용 bind.
  6. this중첩 된 범위 문제를 해결하기위한 복사

47

"이것"은 범위에 관한 것입니다. 모든 함수에는 고유 한 범위가 있으며 JS의 모든 것이 객체이므로 함수조차도 "this"를 사용하여 일부 값을 자체에 저장할 수 있습니다. OOP 101은 "this"는 인스턴스 에만 적용 할 수 있다고 가르칩니다. 객체의 . 따라서 함수가 실행될 때마다 해당 함수의 새로운 "인스턴스"는 "this"라는 새로운 의미를 갖습니다.

대부분의 사람들은 다음과 같은 익명 클로저 함수 내에서 "this"를 사용하려고 할 때 혼란스러워합니다.

(함수 (값) {
    this.value = 값;
    $ ( '. some-elements'). each (function (elt) {
        elt.innerHTML = this.value; // 어 오!! 아마도 정의되지 않은
    });
}) (2);

여기에서 each () 안에서 "this"는 "value"를 기대하지 않습니다.

this.value = 값;
그 위에). 따라서이 문제를 극복하기 위해 개발자는 다음을 수행 할 수 있습니다.

(함수 (값) {
    var self = this; // 작은 변화
    self.value = 가치;
    $ ( '. some-elements'). each (function (elt) {
        elt.innerHTML = self.value; // 휴 !! == 2
    });
}) (2);

사용해보십시오. 이 프로그래밍 패턴을 좋아하기 시작합니다


6
"JS의 모든 것은 객체이다"는 사실이 아니며, 자바 스크립트에도 프리미티브 값이 있습니다. bclary.com/2004/11/07/#a-4.3.2
Marcel Korpel

6
기본 값에는 String # substring (), Number # toString () 등과 같은 일부 메서드가있는 것처럼 보입니다. 따라서 해당 기사와 동일한 명명법을 사용하지 않을 경우 실제로는 마치 객체 인 것처럼 동작합니다. 모든 프로토 타입, 즉 String # substring ()은 실제로 다음과 같습니다. String.prototype.substring = function () {...}). 내가 틀렸다면 정정 해주세요.
arunjitsingh

12
this키워드 범위와는 아무 상관이있다. 또한 객체의 속성이 아닌 함수에서도 의미가 있습니다.
Bergi

1
@arunjitsingh – 그것에 대해 두 가지 생각의 학교가 있습니다. 나는 " 모든 것이 객체이지만 편의를 위해 프리미티브로 표현 될 수있는 것 "을 좋아합니다 . ;-)
RobG

9
this범위에 관한 것은 아닙니다. 실행 컨텍스트에 관한 것은 스코프와 같은 것이 아닙니다. 자바 스크립트는 어휘 범위 (범위는 코드의 위치에 따라 this결정됨 )이지만, 코드 가 포함 된 함수가 어떻게 호출되는지에 따라 결정됩니다.
Scott Marcus

16

이 글타래가 엉망이되어서, 나는 this주제를 처음 접하는 독자들을 위해 몇 가지 요점을 정리했습니다 .

가치는 어떻게 this결정됩니까?

우리는 우리가 영어 같은 자연 언어 대명사를 사용하는 방법과 유사한 사용 : "때문에 요한이 빠른 실행 그가 기차를 잡으려고 노력하고있다." 대신에 우리는“… John 이 기차를 타려고 노력하고 있습니다 ”라고 쓸 수있었습니다 .

var person = {    
    firstName: "Penelope",
    lastName: "Barrymore",
    fullName: function () {

    // We use "this" just as in the sentence above:
       console.log(this.firstName + " " + this.lastName);

    // We could have also written:
       console.log(person.firstName + " " + person.lastName);
    }
}

this 객체는 객체가 정의 된 함수를 호출 할 때까지 값이 할당되지 않습니다 . 전역 범위에서 모든 전역 변수와 함수는 window객체에 정의됩니다 . 그러므로, this전역 함수에서 전역 window객체 를 참조하고 그 값을 갖습니다 .

use strict, this세계에서 어떤 개체에 바인딩되지 않은 익명 함수에서하는의 값을 보유 undefined.

this키워드는 오해 1) 우리가 사용하는 그 방법 빌리 : this2)는 우리가 사용하는 방법을 지정 this변수, 3) 함수가 사용가 this4 콜백 함수로 전달되고,이) this클로저 내에서 사용된다 - 내부 기능. (2)

표

미래를 잡는 것

ECMA Script 6에 정의 된 화살표 기능 this은 둘러싸는 (기능 또는 전역) 범위 의 바인딩을 채택합니다 .

function foo() {
     // return an arrow function
     return (a) => {
     // `this` here is lexically inherited from `foo()`
     console.log(this.a);
  };
}
var obj1 = { a: 2 };
var obj2 = { a: 3 };

var bar = foo.call(obj1);
bar.call( obj2 ); // 2, not 3!

화살표 함수는을 사용하는 대안을 제공하지만 더 널리 이해되는 어휘 범위 지정을 위해 bind()전통적인 this메커니즘을 비활성화한다는 점에 유의해야합니다 . (1)


참고 문헌 :

  1. Kyle & Simpson의 this & Object Prototypes © 2014 Getify 솔루션.
  2. javascriptissexy.com- http : //goo.gl/pvl0GX
  3. 앵거스 크롤 - http://goo.gl/Z2RacU

16

thisJavaScript에서 항상 실행중인 함수의 '소유자'를 나타냅니다 .

명시 적 소유자가 정의되지 않은 경우 최상위 소유자 인 창 개체가 참조됩니다.

내가 한 경우

function someKindOfFunction() {
   this.style = 'foo';
}

element.onclick = someKindOfFunction;

this요소 객체를 참조합니다. 그러나 많은 사람들이이 실수를 저 지르십시오.

<element onclick="someKindOfFunction()">

후자의 경우, 함수를 요소에 넘기는 것이 아니라 함수를 참조 할뿐입니다. 따라서 this창 개체를 참조합니다.


15

자바 스크립트의 모든 실행 컨텍스트 에는 다음에 의해 설정된 this 매개 변수가 있습니다.

  1. 함수 호출 방법 (오브젝트 메소드, 호출적용 사용, new 사용 포함 )
  2. 바인드 사용
  3. 어휘 화살표 기능 (그들이 채택 그 외측의 실행 컨텍스트를)
  4. 코드가 엄격 또는 비 엄격 모드인지 여부
  5. 코드를 사용하여 호출했는지 여부 eval

당신의 값을 설정할 수 있습니다 사용을 func.call, func.apply또는 func.bind.

기본적으로 대부분의 초보자를 혼란스럽게 만드는 요소는 DOM 요소에서 이벤트가 발생한 후 리스너가 호출 될 때 함수 의이 값은 DOM 요소입니다.

jQuery는 jQuery.proxy로이 사소한 변경을 만듭니다.


9
모든 함수 호출 에 범위가 있다고 말하는 것이 조금 더 정확합니다 . 즉, 일에 대해 혼란 this자바 스크립트 것은 점입니다 하지 함수 자체의 고유 재산이 아니라 함수가 호출되는 방식의 유물.
Pointy

@pointy 감사합니다. js에서 이것에 대해 가장 혼란을 일으키는 것은 이전에 사용 된 모든 언어 (c #, c ++)에서 조작 할 수 없다는 것입니다. 기능 사용 func.call, func.bind등 - 수실
수실

2
this함수의 범위를 참조 하지 않습니다 . this특정 개체 (또는 아마도 참조합니다 undefined당신이 사용하여 변경할 수 있습니다 말했듯이), .call()또는 .apply(). 함수의 범위 는 (필수적으로 단순화 될 때) 어떤 변수에 액세스 할 수 있으며, 이는 함수가 선언 된 위치에 따라 달라지며 변경할 수 없습니다.
nnnnnn

@Pointy : "모든 함수 호출에 범위가 있다고 말하는 것이 조금 더 정확합니다." 함수 (및 현재 블록)에 범위가 있고 함수 호출context 가 있다고 말하는 것이 더 정확합니다 . 범위는 해당 범위의 코드에서 사용할 수있는 식별자를 정의합니다. 컨텍스트는 해당 식별자가 바인딩되는 내용을 정의합니다.
TJ Crowder

1
"해당 범위가 무엇이든"this "가 참조합니다." 아니요. this범위는 ES5와 그 이전 (예 :이 답변이 작성된 시점)에서 서로 관련이 없습니다. (일명 ES6) ES2015에서 this및 범위와 관련된 함수 (화살표 WRT 상당히 최소화 방법 this화살표 함수 포위 범위로부터 상속된다)하지만, this범위를 의미하지 않는다.
TJ Crowder

10

여기에 하나의 좋은 소스입니다 this에가 JavaScript.

요약은 다음과 같습니다.

  • 이 글로벌

    브라우저의 글로벌 범위 this에서 window객체는

    <script type="text/javascript">
      console.log(this === window); // true
      var foo = "bar";
      console.log(this.foo); // "bar"
      console.log(window.foo); // "bar"

    에서 nodeREPL을 사용하여, this상단의 네임 스페이스입니다. 이라고 할 수 있습니다 global.

    >this
      { ArrayBuffer: [Function: ArrayBuffer],
        Int8Array: { [Function: Int8Array] BYTES_PER_ELEMENT: 1 },
        Uint8Array: { [Function: Uint8Array] BYTES_PER_ELEMENT: 1 },
        ...
    >global === this
     true

    에서 node, 스크립트에서 실행 this전역에서 빈 객체로 시작합니다. 와 같지 않다global

    \\test.js
    console.log(this);  \\ {}
    console.log(this === global); \\ fasle
  • 이 기능

DOM 이벤트 핸들러의 경우를 제외하고 또는 전역 범위 를 참조하여 호출되지 않은 함수를 thisArg사용하여 노드와 브라우저에서 모두 제공되는 경우 (아래 참조) …thisnew

<script type="text/javascript">
    foo = "bar";

    function testThis() {
      this.foo = "foo";
    }

    console.log(this.foo); //logs "bar"
    testThis();
    console.log(this.foo); //logs "foo"
</script>

당신이 사용하는 경우 use strict;, 그 경우가 this있을 것입니다undefined

<script type="text/javascript">
    foo = "bar";

    function testThis() {
      "use strict";
      this.foo = "foo";
    }

    console.log(this.foo); //logs "bar"
    testThis();  //Uncaught TypeError: Cannot set property 'foo' of undefined 
</script>

당신이 함수를 호출하는 경우 수있는 새로운 상황, 그것은 세계를 참조하지 않습니다 .newthisthis

<script type="text/javascript">
    foo = "bar";

    function testThis() {
      this.foo = "foo";
    }

    console.log(this.foo); //logs "bar"
    new testThis();
    console.log(this.foo); //logs "bar"

    console.log(new testThis().foo); //logs "foo"
</script>
  • 프로토 타입

생성 한 함수는 함수 객체가됩니다. 그들은 자동으로 특별한 prototype속성을 얻습니다 . 이것은 당신이 값을 지정할 수있는 것입니다. 함수를 호출하여 인스턴스를 만들면 속성에 new할당 한 값에 액세스 할 수 있습니다 prototype. 을 사용하여 해당 값에 액세스합니다 this.

function Thing() {
  console.log(this.foo);
}

Thing.prototype.foo = "bar";

var thing = new Thing(); //logs "bar"
console.log(thing.foo);  //logs "bar"

그것은 일반적으로 할당하는 실수 배열 또는 객체prototype. 인스턴스마다 고유 한 배열을 가지려면 프로토 타입이 아닌 함수에서 인스턴스를 생성하십시오.

function Thing() {
    this.things = [];
}

var thing1 = new Thing();
var thing2 = new Thing();
thing1.things.push("foo");
console.log(thing1.things); //logs ["foo"]
console.log(thing2.things); //logs []
  • 이의를 제기하다

당신이 사용할 수있는 this객체에 다른 속성을 참조하는 객체에있는 모든 기능에. 로 만든 인스턴스와 다릅니다 new.

var obj = {
    foo: "bar",
    logFoo: function () {
        console.log(this.foo);
    }
};

obj.logFoo(); //logs "bar"
  • DOM 이벤트는이

HTML DOM 이벤트 핸들러에서 this항상 이벤트가 연결된 DOM 요소에 대한 참조입니다.

function Listener() {
    document.getElementById("foo").addEventListener("click",
       this.handleClick);
}
Listener.prototype.handleClick = function (event) {
    console.log(this); //logs "<div id="foo"></div>"
}

var listener = new Listener();
document.getElementById("foo").click();

bind상황이 아니라면

function Listener() {
    document.getElementById("foo").addEventListener("click", 
        this.handleClick.bind(this));
}
Listener.prototype.handleClick = function (event) {
    console.log(this); //logs Listener {handleClick: function}
}

var listener = new Listener();
document.getElementById("foo").click();
  • HTML이

JavaScript를 넣을 수있는 HTML 속성 내부 this에는 요소에 대한 참조가 있습니다.

<div id="foo" onclick="console.log(this);"></div>
<script type="text/javascript">
document.getElementById("foo").click(); //logs <div id="foo"...
</script>
  • 이것을 평가

eval에 액세스 할 수 있습니다 this.

function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
    eval("console.log(this.foo)"); //logs "bar"
}

var thing = new Thing();
thing.logFoo();
  • 이것으로

당신이 사용할 수있는 with추가 this읽고에 값을 쓰는 현재 범위를 this참조하지 않고 this명시 적으로.

function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
    with (this) {
        console.log(foo);
        foo = "foo";
    }
}

var thing = new Thing();
thing.logFoo(); // logs "bar"
console.log(thing.foo); // logs "foo"
  • jQuery에

jQuery는 여러 곳 this에서 DOM 요소를 참조합니다.

<div class="foo bar1"></div>
<div class="foo bar2"></div>
<script type="text/javascript">
$(".foo").each(function () {
    console.log(this); //logs <div class="foo...
});
$(".foo").on("click", function () {
    console.log(this); //logs <div class="foo...
});
$(".foo").each(function () {
    this.click();
});
</script>

9

대니얼, 대단한 설명! this이벤트 처리기 의 경우이 컨텍스트 목록과 실행 컨텍스트 포인터에 대한 몇 가지 단어 .

즉, thisJavaScript에서 현재 함수가 실행 된 (또는 실행 컨텍스트의) 객체는 항상 읽기 전용이므로 객체를 설정할 수 없습니다 (이러한 시도는 'Invalid left-hand'로 끝납니다) 할당 메시지 쪽.

이벤트 처리기 : 와 같은 인라인 이벤트 처리기는 <element onclick="foo">이전과 이전에 연결된 다른 처리기를 재정의하므로주의하여 인라인 이벤트 위임에서 벗어나는 것이 좋습니다. 그리고 반대 토론을 통해이 예제 목록에 영감을 준 Zara Alaverdyan 덕분에 :)

  • el.onclick = foo; // in the foo - obj
  • el.onclick = function () {this.style.color = '#fff';} // obj
  • el.onclick = function() {doSomething();} // In the doSomething - Window
  • el.addEventListener('click',foo,false) // in the foo - obj
  • el.attachEvent('onclick, function () { // this }') // window, all the compliance to IE :)
  • <button onclick="this.style.color = '#fff';"> // obj
  • <button onclick="foo"> // In the foo - window, but you can <button onclick="foo(this)">

9

JavaScript에서 "this" 키워드가 해석되는 방식과 관련하여 많은 혼란 있습니다. 이 기사가 모든 사람들이 한 번에 휴식을 취하기를 바랍니다. 그리고 훨씬 더. 전체 기사를주의 깊게 읽으십시오. 이 기사는 길다.

사용되는 컨텍스트와 상관없이 "this"는 항상 Javascript 의 "현재 오브젝트" 를 참조합니다 . 그러나 "현재 객체"context 에 따라 다릅니다 . 상황은 정확히 할 수있다 1 (6)의 다음과 같은 :

  1. 글로벌 (즉, 모든 기능 외부)
  2. 직접 "바인드되지 않은 함수"호출 내부 (즉, functionName.bind를 호출하여 바인드 되지 않은 함수 )
  3. 내부 간접 "비 바운드 함수" functionName.callfunctionName.apply를 통한 호출
  4. "바운드 함수"호출 내부 (즉, functionName.bind를 호출하여 바인딩함수 )
  5. "신규"를 통한 객체 생성
  6. 인라인 DOM 이벤트 핸들러 내부

다음은 이러한 각 컨텍스트를 하나씩 설명합니다.

  1. 글로벌 컨텍스트 (즉, 모든 기능 외부) :

    모든 함수 외부에서 (즉, 전역 컨텍스트에서) "현재 객체" (따라서 "this" 값 )는 항상 브라우저 의 "창" 객체입니다.

  2. 직접 "비 바운드 기능"호출 내부 :

    직접 "바인딩되지 않은 함수" 호출 내에서 함수 호출을 호출 한 오브젝트는 "현재 오브젝트" (따라서 "this" 값 )가됩니다. 명시 적 현재 객체 없이 함수가 호출 되면 현재 객체"창" 객체 (비 엄격 모드의 경우) 또는 정의되지 않은 (엄격한 모드의 경우)입니다. 전역 컨텍스트에 정의 된 모든 함수 (또는 변수)는 자동으로 "창" 개체 의 속성이됩니다. 예를 들어 함수가 전역 컨텍스트에 다음과 같이 정의되어 있다고 가정합니다.

    function UserDefinedFunction(){
        alert(this)
        }

    다음과 같이 정의한 것처럼 창 객체의 속성이됩니다.

    window.UserDefinedFunction=function(){
      alert(this)
    }  

    "비 엄격 모드"직접 통해 함수를 호출 / 호출 '() UserDefinedFunction " 자동적으로 / 호출 호출 "window.UserDefinedFunction () " 제작 "창 " 은 AS "현재 대상 " 의 (따라서 값을 " "이 이내) UserDefinedFunction" " 비 엄격 모드에서이 기능을 .Invoking는" "다음에 발생합니다

    UserDefinedFunction() // displays [object Window]  as it automatically gets invoked as window.UserDefinedFunction()

    "Strict Mode"에서 "UserDefinedFunction ()"을 통해 직접 함수 호출 / 호출 은 "NOT"가 자동으로 "window.UserDefinedFunction ()" 으로 호출 / 호출합니다. 따라서 "현재 객체" (및 "this" 의 값) "UserDefinedFunction" 내에서 정의되지 않아야합니다 . "엄격 모드"에서이 기능을 호출하면 다음과 같은 결과가 나타납니다.

    UserDefinedFunction() // displays undefined

    그러나 window 객체를 사용하여 명시 적으로 호출하면 다음과 같은 결과가 발생합니다

    window.UserDefinedFunction() // "always displays [object Window]   irrespective of mode."

    다른 예를 보자. 다음 코드를 참조하십시오

     function UserDefinedFunction()
        {
            alert(this.a + ","  + this.b + ","  + this.c  + ","  + this.d)
        }
    
    var o1={
                a:1,
                b:2,
                f:UserDefinedFunction
          }
    var o2={
                c:3,
                d:4,
                f:UserDefinedFunction
           }
    
    o1.f() // Shall display 1,2,undefined,undefined
    o2.f() // Shall display undefined,undefined,3,4

    위의 예제에서 "UserDefinedFunction"o1을 통해 호출 되면 "this"o1 의 값을 가져 오고 해당 속성 "a""b"의 값 이 표시됩니다. 값 "C""D"는 것으로 도시 된 미정 같이 O1은 이러한 특성을 정의하지 않는다

    때 마찬가지로 "UserDefinedFunction은" 을 호출 O2 , "이" 의 값을 취 O2 와 그 속성의 값을 "C""D"를 의 displayed.The 값을 얻는 "A""B"를 로서 도시 된 미정 로서 O2가 수행 이러한 속성을 정의하지 마십시오.

  3. 내부 간접 "비 바운드 함수" functionName.callfunctionName.apply를 통해 호출 합니다 .

    "비 바인딩 기능" 으로 불린다 functionName.call 또는 functionName.apply"현재 대상" (그리고 따라서 값 "이" )의 값으로 설정 "이" 에 전달 파라미터 (제 1 파라미터) 콜 / 적용 . 다음 코드는 동일하게 보여줍니다.

    function UserDefinedFunction()
    {
        alert(this.a + ","  + this.b + ","  + this.c  + ","  + this.d)
    }
    var o1={
                a:1,
                b:2,
                f:UserDefinedFunction
           }
    var o2={
                c:3,
                d:4,
                f:UserDefinedFunction
           }
    
    UserDefinedFunction.call(o1) // Shall display 1,2,undefined,undefined
    UserDefinedFunction.apply(o1) // Shall display 1,2,undefined,undefined
    
    UserDefinedFunction.call(o2) // Shall display undefined,undefined,3,4
    UserDefinedFunction.apply(o2) // Shall display undefined,undefined,3,4
    
    o1.f.call(o2) // Shall display undefined,undefined,3,4
    o1.f.apply(o2) // Shall display undefined,undefined,3,4
    
    o2.f.call(o1) // Shall display 1,2,undefined,undefined
    o2.f.apply(o1) // Shall display 1,2,undefined,undefined

    위의 코드는 "NON Bound Function"의 "this"값이 call / apply를 통해 변경 될 수 있음을 분명히 보여줍니다 . 경우에도 "이" 매개 변수를 명시 적으로 전달되지 않는 호 / 적용 , "현재 대상" (따라서 "이는"의 값)로 설정 "윈도우" 비 엄격 모드와 "미등록" 엄격한 모드.

  4. "바운드 함수"호출 내부 (즉, functionName.bind를 호출하여 바인딩 된 함수 ) :

    바운드 함수는 "this" 값이 수정 된 함수입니다 . 다음 코드 는 바운드 함수의 경우 "this"의 작동 방식을 보여줍니다.

    function UserDefinedFunction()
    {
        alert(this.a + ","  + this.b + ","  + this.c  + ","  + this.d)
    }
    var o1={
              a:1,
              b:2,
              f:UserDefinedFunction,
              bf:null
           }
    var o2={
               c:3,
               d:4,
               f:UserDefinedFunction,
               bf:null
            }
    
    var bound1=UserDefinedFunction.bind(o1); // permanantly fixes "this" value of function "bound1" to Object o1
    bound1() // Shall display 1,2,undefined,undefined
    
    var bound2=UserDefinedFunction.bind(o2); // permanantly fixes "this" value of function "bound2" to Object o2
    bound2() // Shall display undefined,undefined,3,4
    
    var bound3=o1.f.bind(o2); // permanantly fixes "this" value of function "bound3" to Object o2
    bound3() // Shall display undefined,undefined,3,4
    
    var bound4=o2.f.bind(o1); // permanantly fixes "this" value of function "bound4" to Object o1
    bound4() // Shall display 1,2,undefined,undefined
    
    o1.bf=UserDefinedFunction.bind(o2) // permanantly fixes "this" value of function "o1.bf" to Object o2
    o1.bf() // Shall display undefined,undefined,3,4
    
    o2.bf=UserDefinedFunction.bind(o1) // permanantly fixes "this" value of function "o2.bf" to Object o1
    o2.bf() // Shall display 1,2,undefined,undefined
    
    bound1.call(o2) // Shall still display 1,2,undefined,undefined. "call" cannot alter the value of "this" for bound function
    
    bound1.apply(o2) // Shall still display 1,2,undefined,undefined. "apply" cannot alter the value of "this" for bound function
    
    o2.bf.call(o2) // Shall still display 1,2,undefined,undefined. "call" cannot alter the value of "this" for bound function
    o2.bf.apply(o2) // Shall still display 1,2,undefined,undefined."apply" cannot alter the value of "this" for bound function

    위 코드에서 주어진 것처럼, "바운드 함수"에 대한 "this"값은 call / apply를 통해 변경할 수 없습니다 . 또한 "this" 매개 변수가 바인드하도록 명시 적으로 전달되지 않은 경우 , "현재 오브젝트" (따라서 "this" 값 )는 엄격하지 않은 모드에서는 "window" 로 설정되고 엄격 모드에서는 "undefined" 로 설정됩니다. 하나 더. 이미 바인딩 된 함수를 바인딩해도 "this" 값은 변경되지 않습니다 . 첫 번째 바인드 기능에 의해 설정된 값으로 설정되어 있습니다.

  5. "신규"를 통한 객체 생성 :

    생성자 함수 내에서 "현재 객체" (따라서 "this" 값 ) 는 함수의 바인드 상태에 관계없이 "new"를 통해 현재 생성중인 객체를 참조합니다 . 그러나 생성자가 바운드 함수 인 경우 바운드 함수에 대해 설정된 미리 정의 된 인수 집합으로 호출됩니다.

  6. 인라인 DOM 이벤트 핸들러 내부 :

    다음 HTML 스 니펫을보십시오

    <button onclick='this.style.color=white'>Hello World</button>
    <div style='width:100px;height:100px;' onclick='OnDivClick(event,this)'>Hello World</div>

    "이" 위의 예는 각각 "버튼"요소와 "DIV"요소를 참조한다.

    첫 번째 예에서, 버튼의 글꼴 색상은 클릭시 흰색으로 설정됩니다.

    두 번째 예제에서 "div" 요소를 클릭 하면 클릭 한 div 요소를 참조하는 두 번째 매개 변수와 함께 OnDivClick 함수를 호출해야합니다 . 그러나 OnDivClick 내의 "this" 값은 클릭 된 div 요소를 참조 하지 않습니다 . 그것이로 설정한다 "윈도우 객체" 또는 "미등록"비 엄격 하고 엄격한 모드 (경우 각각 OnDivClick가바인드 기능 소정 바운드 값) 또는 세트 (경우 OnDivClick는 A는 결합 된 기능 )

다음은 전체 기사를 요약 한 것입니다

  1. 글로벌 컨텍스트에서 "this"는 항상 "window" 개체를 나타냅니다.

  2. 함수가 호출 될 때마다 객체 ( "현재 객체" )의 컨텍스트에서 호출됩니다 . 경우 현재의 객체가 명시 적으로 제공되지는 현재 객체 는 IS "창 객체"비 엄격 모드"정의되지 않은" 기본적으로 엄격한 모드.

  3. 비 바인드 함수 내에서 "this" 값은 함수가 호출 된 컨텍스트에서 오브젝트에 대한 참조입니다 ( "current object" )

  4. 비 바인드 함수 내의 "this" 값은 함수의 호출적용 메소드 로 대체 될 수 있습니다 .

  5. "this" 값은 바운드 함수에 대해 고정되어 있으며 함수의 호출적용 메소드 로 대체 할 수 없습니다 .

  6. 바인딩 및 이미 바인딩 된 함수는 "this"의 값을 변경하지 않습니다. 첫 번째 바인드 기능에 의해 설정된 값으로 설정되어 있습니다.

  7. 생성자 내의 "this" 값은 생성 및 초기화되는 객체입니다.

  8. 인라인 DOM 이벤트 핸들러 내의 "this" 값은 이벤트 핸들러가 제공되는 요소에 대한 참조입니다.


9

아마도 가장 상세하고 포괄적 인 기사 this는 다음과 같습니다.

JavaScript에서 'this'키워드에 대한 부드러운 설명

배후의 아이디어 this는 함수 호출 유형이 this값 설정에 매우 중요하다는 것을 이해하는 것입니다 .


를 식별하는 데 문제가있는 this경우 스스로에게 묻지 마십시오 .

어디에서 this가져 옵니까 ?

그러나 않는 자신에게 물어 :

함수는 어떻게 호출 됩니까?

화살표 기능 (컨텍스트 투명도의 특수한 경우)에 대해서는 다음과 같이 자문하십시오.

어떤 것은 가치있다 this화살표 함수된다 정의 ?

이 사고 방식은 대처할 때 정확 this하며 두통을 예방합니다.


블로그에 연결하는 것 외에도 이러한 질문을하는 것이 누군가가 this키워드를 이해하는 데 어떻게 도움이되는지 좀 더 깊이 파고들 수 있습니까?
Magnus Lind Oxlund

7

: 이것은 내가 본 최고의 설명입니다 자바 스크립트 이해 명확성을

기준 ALWAYS를 지칭 (및의 값을 보유하고있다)가 전역에 기능 밖에 사용할 수 있지만 객체 단수는 물체와이 통상 함수 또는 방법 내에서 사용된다. 엄격 모드를 사용하면 전역 함수와 객체에 바인딩되지 않은 익명 함수에서 undefined 값이 유지됩니다.

네 가지 시나리오가있다 혼란 스러울 수는 :

  1. 콜백 함수로 사용될 인자로 메소드 ( this 를 사용 하는 )를 전달할 때 .
  2. 내부 함수 (클로즈)를 사용할 때. 클로저는 this 키워드를 사용하여 외부 함수 의이 변수에 액세스 할 수 없다는 점에 유의해야 합니다.이 변수는 내부 함수가 아닌 함수 자체만으로 액세스 할 수 있기 때문입니다.
  3. 에 의존하는 방법 때 이는 경우에 컨텍스트에서 변수에 할당되는 원래 의도 한 것보다 참조를 다른 개체를.
  4. 이것을 바인드, 적용 및 호출 메소드와 함께 사용할 때 .

그는 코드 예제, 설명 및 솔루션을 제공하며 매우 유용하다고 생각했습니다.


6

유사 고전 용어로, 많은 강의에서 'this'키워드를 가르치는 방식은 클래스 또는 객체 생성자가 인스턴스화 한 객체입니다. 클래스에서 새 객체를 만들 때마다 'this'객체의 로컬 인스턴스가 만들어지고 반환된다고 상상해보십시오. 나는 이것이 이렇게 가르쳤다는 것을 기억한다.

function Car(make, model, year) {
var this = {}; // under the hood, so to speak
this.make = make;
this.model = model;
this.year = year;
return this; // under the hood
}

var mycar = new Car('Eagle', 'Talon TSi', 1993);
// ========= under the hood
var this = {};
this.make = 'Eagle';
this.model = 'Talon TSi';
this.year = 1993;
return this;

5

this자바 스크립트에서 오해의 여지가있는 개념 중 하나입니다. 간단히 말해서 현재 실행중인 함수this"소유자"를 나타냅니다 .

this현재 객체 (일명 실행 컨텍스트)를 얻는 데 도움이됩니다. 현재 함수가 어떤 객체에서 실행되는지 이해하면 전류 this가 무엇인지 쉽게 이해할 수 있습니다.

var val = "window.val"

var obj = {
    val: "obj.val",
    innerMethod: function () {
        var val = "obj.val.inner",
            func = function () {
                var self = this;
                return self.val;
            };

        return func;
    },
    outerMethod: function(){
        return this.val;
    }
};

//This actually gets executed inside window object 
console.log(obj.innerMethod()()); //returns window.val

//Breakdown in to 2 lines explains this in detail
var _inn = obj.innerMethod();
console.log(_inn()); //returns window.val

console.log(obj.outerMethod()); //returns obj.val

위의 이름은 'val'인 3 개의 변수를 만듭니다. 하나는 전역 컨텍스트에서 하나는 obj 내부이고 다른 하나는 obj의 innerMethod 내부입니다. JavaScript는 로컬 Go Global에서 범위 체인으로 올라가 특정 컨텍스트 내에서 식별자를 확인합니다.


this차별화 할 수있는 곳 은 거의 없습니다

객체의 메소드 호출

var status = 1;
var helper = {
    status : 2,
    getStatus: function () {
        return this.status;
    }
};

var theStatus1 = helper.getStatus(); //line1
console.log(theStatus1); //2

var theStatus2 = helper.getStatus;
console.log(theStatus2()); //1

line1이 실행될 때, JavaScript는 함수 호출을위한 실행 컨텍스트 (EC)를 설정 하고 마지막 "."이전의 모든 항목이 참조this 하는 객체로 설정 합니다 . . 마지막 줄 a()에서 전역 컨텍스트에서 실행 된 것을 이해할 수 있습니다 window.

생성자

this 생성되는 객체를 참조하는 데 사용할 수 있습니다

function Person(name){
    this.personName = name;
    this.sayHello = function(){
        return "Hello " + this.personName;
    }
}

var person1 = new Person('Scott');
console.log(person1.sayHello()); //Hello Scott

var person2 = new Person('Hugh');
var sayHelloP2 = person2.sayHello;
console.log(sayHelloP2()); //Hello undefined

new Person()가 실행되면 완전히 새로운 객체가 생성됩니다. Person이 호출되고 this새 객체를 참조하도록 설정됩니다.

함수 호출

function testFunc() {
    this.name = "Name";
    this.myCustomAttribute = "Custom Attribute";
    return this;
}

var whatIsThis = testFunc();
console.log(whatIsThis); //window

var whatIsThis2 = new testFunc();
console.log(whatIsThis2);  //testFunc() / object

console.log(window.myCustomAttribute); //Custom Attribute 

new키워드 를 놓치면 whatIsThis찾을 수있는 가장 전역적인 컨텍스트를 나타냅니다 ( window)

이벤트 처리기

이벤트 핸들러가 인라인 인 경우 this글로벌 오브젝트를 참조하십시오.

<script type="application/javascript">
    function click_handler() {
        alert(this); // alerts the window object
    }
</script>

<button id='thebutton' onclick='click_handler()'>Click me!</button>

JavaScript를 통해 이벤트 핸들러를 추가 할 때 이벤트 this를 생성 한 DOM 요소를 나타냅니다.



5

"this"의 값은 함수가 실행되는 "context"에 따라 다릅니다. 콘텍스트는 임의의 객체 또는 글로벌 객체, 즉 윈도우 일 수있다.

"this"의 의미는 전통적인 OOP 언어와 다릅니다. 그리고 그것은 문제를 일으킨다 : 1. 함수가 다른 변수 (대부분 콜백)에 전달 될 때; 그리고 2. 클래스의 멤버 메소드에서 클로저가 호출 될 때.

두 경우 모두 window로 설정됩니다.


3

Whould 도움? (자바 스크립트에서 'this'의 혼동은 일반적으로 객체와 연결되어 있지 않지만 현재 실행 범위와 일치한다는 사실에서 비롯됩니다. 정확히 작동하는 방식은 아니지만 항상 나에게 그런 느낌입니다. 자세한 설명은 기사 참조)


1
" 현재 실행 컨텍스트 "에 링크되어 있다고 말하는 것이 좋습니다 . ES6 (초안)을 제외하고 화살표 기능으로 변경하면 외부 실행 컨텍스트에서 해결됩니다.
RobG

3

키워드 에 대한 약간의 정보

this코드를 추가하지 않고 전역 범위에서 콘솔에 키워드를 기록해 봅시다.

console.log(this)

에서 클라이언트 / 브라우저 this 키워드는 글로벌 오브젝트입니다window

console.log(this === window) // true

에서 서버 / 노드 / 자바 스크립트 런타임 this 키워드는 글로벌 오브젝트도module.exports

console.log(this === module.exports) // true
console.log(this === exports) // true

명심는 exports단지 참조입니다module.exports


1

이처럼 범위에 대한 사용

  <script type="text/javascript" language="javascript">
$('#tbleName tbody tr').each(function{
var txt='';
txt += $(this).find("td").eq(0).text();
\\same as above but synatx different
var txt1='';
 txt1+=$('#tbleName tbody tr').eq(0).text();
alert(txt1)
});
</script>

위의 예에서 txt1과 txt의 값은 동일합니다 $ (this) = $ ( '# tbleName tbody tr') is Same


1

나는 다른 걸릴 this도움이되기를 바랍니다. 다른 답변 가 있습니다.

JavaScript를 보는 한 가지 방법은 함수 1 을 호출하는 단 하나의 방법 만 있음을 보는 것입니다 . 그것은

functionObject.call(objectForThis, arg0, arg1, arg2, ...);

에 제공되는 값이 항상 있습니다 objectForThis.

다른 모든 것들은 구문 설탕입니다 functionObject.call

따라서 다른 모든 것은로 변환되는 방식으로 설명 할 수 있습니다 functionObject.call.

방금 함수를 호출 this하면 브라우저에서 창이 "글로벌 객체"입니다

function foo() {
  console.log(this);
}

foo();  // this is the window object

다시 말해,

foo();

효과적으로 번역되었다

foo.call(window);

엄격 모드를 사용 this하면undefined

'use strict';

function foo() {
  console.log(this);
}

foo();  // this is the window object

그 의미는

다시 말해,

foo();

효과적으로 번역되었다

foo.call(undefined);

JavaScript에는 +and -및 같은 연산자가 있습니다 *. 도트 연산자도 있습니다..

.오른쪽 함수 및 왼쪽 목적으로 사용 연산자 효과적으로 "패스 대상인 수단this 기능.

const bar = {
  name: 'bar',
  foo() { 
    console.log(this); 
  },
};

bar.foo();  // this is bar

bar.foo()로 변환const temp = bar.foo; temp.call(bar);

함수가 어떻게 생성되었는지는 중요하지 않습니다 (주로 ...). 이 모든 것들은 같은 결과를 낳을 것입니다

const bar = {
  name: 'bar',
  fn1() { console.log(this); },
  fn2: function() { console.log(this); },
  fn3: otherFunction,
};

function otherFunction() { console.log(this) };

bar.fn1();  // this is bar
bar.fn2();  // this is bar
bar.fn3();  // this is bar

다시 이것들은 모두 단지 구문 설탕입니다

{ const temp = bar.fn1; temp.call(bar); }
{ const temp = bar.fn2; temp.call(bar); }
{ const temp = bar.fn3; temp.call(bar); }

또 다른 주름은 프로토 타입 체인입니다. a.bJavaScript 를 사용할 때 먼저 a속성 에 대해 직접 참조하는 객체를 찾습니다 b. 경우 b개체에 발견되지 않는 다음 자바 스크립트를 찾을 수있는 객체의 프로토 타입에서 찾게됩니다 b.

객체의 프로토 타입을 정의하는 다양한 방법이 있으며 2019 년에 가장 일반적으로 class키워드입니다. this중요하지 않지만 목적을 위해 . 중요한 것은 객체 a에서 속성 b을 찾은 경우 객체 를 찾 b거나 프로토 타입 체인에서 속성 을 찾으면 속성 b과 동일한 규칙이 적용된다는 것입니다. 함수 b참조는 call메소드를 사용하여 호출 a되며이 답변의 맨 위에 표시된 것처럼 objectForThis로 전달 됩니다.

지금. this다른 함수를 호출하기 전에 명시 적으로 설정 한 다음 .(점) 연산자로 호출 하는 함수를 상상해 봅시다.

function foo() {
  console.log(this);
}

function bar() {
  const objectForThis = {name: 'moo'}
  foo.call(objectForThis);  // explicitly passing objectForThis
}

const obj = {
  bar,
};

obj.bar();  

사용에 번역에 따라 call, obj.bar()이된다 const temp = obj.bar; temp.call(obj);. bar함수 를 입력하면 호출 foo하지만 objectForThis에 대한 다른 객체를 명시 적으로 전달하므로 foo에 도달하면this 내부 객체가됩니다.

이것이 바로 기능 bind=>기능입니다. 그들은 더 구문 설탕입니다. 지정된 함수를 호출하기 전에 bar명시 적으로 설정하는 위와 같은 새로운 보이지 않는 함수를 효과적으로 작성 this합니다. 바인드의 경우 this전달하는 대상으로 설정됩니다 bind.

function foo() {
  console.log(this);
}

const bar = foo.bind({name: 'moo'});

// bind created a new invisible function that calls foo with the bound object.

bar();  

// the objectForThis we are passing to bar here is ignored because
// the invisible function that bind created will call foo with with
// the object we bound above

bar.call({name: 'other'});

경우 참고 functionObject.bind존재하지 않았다 우리는이 같은 우리의 자신의 만들 수

function bind(fn, objectForThis) {
  return function(...args) {
    return fn.call(objectForthis, ...args);
  };
}

우리는 이것을 이렇게 부를 수 있습니다

function foo() {
  console.log(this);
}

const bar = bind(foo, {name:'abc'});

화살표 기능, =>연산자는 바인드에 대한 구문 설탕입니다

const a = () => {console.log(this)};

와 같다

const tempFn = function() {console.log(this)}; 
const a = tempFn.bind(this);

마찬가지로 bind, 바인딩되지 않은 새로운 함수가 생성되어 바인딩 된 객체 objectForThisbind는 달리 바인딩 된 값으로 지정된 함수를 호출합니다 . this때 일어날 무슨 일이=> 연산자를 사용한다.

위의 규칙과 마찬가지로

const a = () => { console.log(this); }  // this is the global object
'use strict';
const a = () => { console.log(this); }  // this is undefined
function foo() {
  return () => { console.log(this); }
}

const obj = {
  foo,
};
const b = obj.foo();
b();

obj.foo()로 변환하면 const temp = obj.foo; temp.call(obj);내부의 화살표 연산자 가 새로운 보이지 않는 함수에 foo바인딩 obj되고에 지정된 새로운 보이지 않는 함수를 반환합니다 b. b()항상 새로운 보이지 않는 함수를 만들 b.call(window)거나 b.call(undefined)호출 한대로 작동합니다 foo. 보이지 않는 함수는 this전달 된 것을 무시 obj하고 화살표 함수에 objectForThis`로 전달 합니다.

위의 코드는

function foo() {
  function tempFn() {
    console.log(this);
  }
  return tempFn.bind(this);
}

const obj = {
  foo,
};
const b = obj.foo();
b.call(window or undefined if strict mode);

1apply 은 비슷한 다른 기능입니다call

functionName.apply(objectForThis, arrayOfArgs);

그러나 ES6부터 개념적으로는

functionName.call(objectForThis, ...arrayOfArgs);

0

this자바 스크립트 요약 :

  • 의 값은 함수가 호출 된 위치가 아닌 위치에this 의해 결정됩니다 .
  • 일반적으로의 값은 this점의 왼쪽에있는 Object에 의해 결정됩니다. ( window글로벌 우주에서)
  • 이벤트 리스너에서 값은 this 이벤트가 호출 된 DOM 요소를 나타냅니다.
  • 함수에서 new키워드를 사용하여 호출하면 의 값은 this새로 작성된 오브젝트 를 나타냅니다.
  • 당신은 값 조작 할 수있는 this기능과을 : call, apply,bind

예:

let object = {
  prop1: function () {console.log(this);}
}

object.prop1();   // object is left of the dot, thus this is object

const myFunction = object.prop1 // We store the function in the variable myFunction

myFunction(); // Here we are in the global space
              // myFunction is a property on the global object
              // Therefore it logs the window object
              
             

이벤트 리스너 예 :

document.querySelector('.foo').addEventListener('click', function () {
  console.log(this);   // This refers to the DOM element the eventListener was invoked from
})


document.querySelector('.foo').addEventListener('click', () => {
  console.log(this);  // Tip, es6 arrow function don't have their own binding to the this v
})                    // Therefore this will log the global object
.foo:hover {
  color: red;
  cursor: pointer;
}
<div class="foo">click me</div>

생성자 예제 :

function Person (name) {
  this.name = name;
}

const me = new Person('Willem');
// When using the new keyword the this in the constructor function will refer to the newly created object

console.log(me.name); 
// Therefore, the name property was placed on the object created with new keyword.


0

"이것"을 제대로 이해하려면 문맥과 범위, 그리고 차이점을 이해해야합니다.

범위 : 자바 스크립트 범위에서 변수의 가시성과 관련이 있으며, 범위는 함수의 사용을 통해 달성됩니다. (범위에 대해 자세히 알아보십시오)

컨텍스트 : 컨텍스트는 객체와 관련이 있습니다. 함수가 속한 객체를 말합니다. JavaScript "this"키워드를 사용하면 함수가 속한 객체를 나타냅니다. 예를 들어 함수 내부에서 "this.accoutNumber"라고 말하면 해당 함수가 속한 개체에 속하는 "accoutNumber"속성을 참조하는 것입니다.

“myObj”객체에“getMyName”이라는 메소드가있는 경우“getMyName”내부에서 JavaScript 키워드“this”가 사용되면“myObj”를 나타냅니다. "getMyName"기능이 전역 범위에서 실행 된 경우 "this"는 윈도우 객체를 나타냅니다 (엄격 모드 제외).

이제 몇 가지 예를 보자.

    <script>
        console.log('What is this: '+this);
        console.log(this);
    </script>

브라우저 출력에서 ​​Runnig abobve 코드는 다음과 같습니다. 여기에 이미지 설명을 입력하십시오

창 개체의 컨텍스트 안에있는 출력에 따르면 창 프로토 타입이 개체를 참조하는 것도 표시됩니다.

이제 함수 안에서 시도해 보자.

    <script>
        function myFunc(){
            console.log('What is this: '+this);
            console.log(this);
        }
        myFunc();
    </script>

산출:

여기에 이미지 설명을 입력하십시오 전역 범위에 'this'변수를 기록하고 기능 범위에 기록했기 때문에 결과는 동일합니다. 컨텍스트를 변경하지 않았습니다. 두 경우 모두 widow object 와 관련하여 컨텍스트가 동일 합니다 .

이제 우리 자신의 객체를 만들어 봅시다. 자바 스크립트에서는 여러 가지 방법으로 객체를 만들 수 있습니다.

 <script>
        var firstName = "Nora";
        var lastName = "Zaman";
        var myObj = {
            firstName:"Lord",
            lastName:'Baron',
            printNameGetContext:function(){
                console.log(firstName + " "+lastName);
                console.log(this.firstName +" "+this.lastName);
                return this;
            }
        }

      var context = myObj.printNameGetContext();
      console.log(context);
    </script>

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

위의 예에서 'this'키워드는 myObj와 관련된 새로운 컨텍스트를 참조하고 있으며 myObject에는 Object에 대한 프로토 타입 체인도 있습니다.

다른 예를 들어 봅시다 :

<body>
    <button class="btn">Click Me</button>
    <script>
        function printMe(){
            //Terminal2: this function declared inside window context so this function belongs to the window object.
            console.log(this);
        }
        document.querySelector('.btn').addEventListener('click', function(){
            //Terminal1: button context, this callback function belongs to DOM element 
            console.log(this);
            printMe();
        })
    </script>
</body>

출력 : 이해가 되나요? (댓글 읽기) 여기에 이미지 설명을 입력하십시오

위 예제를 이해하는데 어려움이 있다면, 우리 자신의 콜백을 시도해 보자.

<script>
        var myObj = {
            firstName:"Lord",
            lastName:'Baron',
            printName:function(callback1, callback2){
                //Attaching callback1 with this myObj context
                this.callback1 = callback1;
                this.callback1(this.firstName +" "+this.lastName)
                //We did not attached callback2 with myObj so, it's reamin with window context by default
                callback2();
                /*
                 //test bellow codes
                 this.callback2 = callback2;
                 this.callback2();
                */
            }
        }
        var callback2 = function (){
            console.log(this);
        }
        myObj.printName(function(data){
            console.log(data);
            console.log(this);
        }, callback2);
    </script>

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

이제 범위, 자기, IIFE 및이 동작을 이해하자

       var color = 'red'; // property of window
       var obj = {
           color:'blue', // property of window
           printColor: function(){ // property of obj, attached with obj
               var self = this;
               console.log('In printColor -- this.color: '+this.color);
               console.log('In printColor -- self.color: '+self.color);
               (function(){ // decleard inside of printColor but not property of object, it will executed on window context.
                    console.log(this)
                    console.log('In IIFE -- this.color: '+this.color);
                    console.log('In IIFE -- self.color: '+self.color); 
               })();

               function nestedFunc(){// decleard inside of printColor but not property of object, it will executed on window context.
                    console.log('nested fun -- this.color: '+this.color);
                    console.log('nested fun -- self.color: '+self.color);
               }

               nestedFunc(); // executed on window context
               return nestedFunc;
           }
       };

       obj.printColor()(); // returned function executed on window context
   </script> 

출력이 정말 굉장합니까? 여기에 이미지 설명을 입력하십시오


-1

간단한 답변 :

"this"키워드는 항상 호출 컨텍스트에 따라 다릅니다. 아래에 언급되어 있습니다.

  1. 새로운 키워드로 기능 호출

    함수가 NEW 키워드로 호출되면 THIS는 새로 작성된 오브젝트에 바인드됩니다.

    function Car(){
      this.name="BMW";
    }
    const myCar=new Car();
    myCar.name; // output "BMW"

    위의 'myCar'객체에 바인딩됩니다.

  2. 통화 및 적용 방법을 사용하여 기능이 명시 적으로 호출됩니다.

    이 경우 THIS는 명시 적으로 함수에 전달되는 객체에 바인딩됩니다.

    var obj1={"name":"bond"};
    function printMessage(msg){
        return msg+" "+this.name;
    }
    const message=printMessage.call(obj1,"my name is ");
    console.log(message); //HERE THIS WILL BE BOUND TO obj1 WHICH WE PASSED EXPLICITLY. SAME FOR APPLY METHOD ALSO.
  3. 기능이 부정확하게 개체에 호출 된 경우 해당 개체에 적용됩니다.

    var obj1={
       "name":"bond",
        getName: function () {
                    return this.name;
                 }
    };
    const newname=obj1.getName();
    console.log(newname); //HERE THIS WILL BE BOUND TO obj1(WHITCHEVER OBJECT IS MENTIONED BEFORE THE DOT THIS WILL BE BOUND TO THAT)
  4. 컨텍스트없이 함수를 호출하면 글로벌 오브젝트에 바인드됩니다.

    const util = {
       name: 'Utility',
       getName: function () {
                    return this.name;
    };
    
    const getName=util.getName;
    const newName=getName();
    console.log(newName); // IF THIS EXECUTED IN BROWSER THIS WILL BE  BOUND TO WINDOW OBJECT. IF THIS EXECUTED IN SERVER THIS WILL BE BOUND TO GLOBAL OBJECT
  5. 엄격 모드에서는이 정의가 정의되지 않습니다

    function setName(name){
        "use strict"
        return this.name;
    }
    setName(); //WILL BE ERROR SAYING name IS UNDEFINED. 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.