[javascript] “this”키워드는 어떻게 작동합니까?
나는 무엇에 대한 명확한 설명이없는 것으로 나타났습니다 this
키워드가 키워드가 스택 오버플로 사이트의 JavaScript에서 올바르게 (잘못) 사용되는 방법에 .
나는 그것에 대해 매우 이상한 행동을 목격했으며 왜 그런 일이 일어 났는지 이해하지 못했습니다.
어떻게 this
작동하고 언제 사용해야합니까?
답변
Mike West 의 기사 Scope in JavaScript ( mirror )를 먼저 읽는 것이 좋습니다 . 그것은 개념에 대한 훌륭하고 친근한 소개입니다.this
JavaScript 과 범위 체인에 입니다.
에 익숙해지기 시작 this
하면 규칙은 실제로 매우 간단합니다. 인 ECMAScript 5.1 표준 을 정의 this
:
§11.1.1
this
키워드
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
기능이 지정된 callbackfn
ThisBinding로 설정 실행 컨텍스트에서 호출 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
합니다.
재미를 위해 몇 가지 예를 통해 이해를 테스트하십시오.
답을 나타내려면 밝은 회색 상자 위로 마우스를 이동하십시오.
-
의 가치는 무엇입니까
this
표시된 줄 얼마입니까? 왜?window
— 표시된 행은 초기 전역 실행 컨텍스트에서 평가됩니다.if (true) { // What is `this` here? }
-
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);
-
this
표시된 줄 의 값은 얼마입니까? 왜?window
이 예제에서 JavaScript 인터프리터는 함수 코드를 입력하지만
myFun
obj.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);
-
this
표시된 줄 의 값은 얼마입니까? 왜?window
이건 까다로웠다. 평가 코드를 평가할 때는
this
입니다obj
. 그러나 평가 코드에서는myFun
개체에서 호출되지 않으므로 ThisBinding이window
호출로 설정됩니다 .function myFun() { return this; // What is `this` here? } var obj = { myMethod: function () { eval("myFun()"); } };
-
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);
답변
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])
insideobj1
의 값으로 설정 하고 인수로 전달되는 요소를 호출합니다 .this
fun()
fun()
argsArray
fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])
– 내부obj1
값으로 설정 하고 인수로 전달하는 호출 .this
fun()
fun()
arg1, arg2, arg3, ...
fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])
– 기능에 대한 참조를 반환fun
과this
내부에 결합 재미obj1
와의 매개 변수에fun
지정된 매개 변수에 바인딩을arg1, arg2, arg3,...
.- 지금까지 사이의 차이
apply
,call
그리고bind
명확하게해야합니다.apply
배열과 같은 객체, 즉 숫자length
속성과 해당하는 음이 아닌 정수 속성을 가진 객체로 작동하는 인수를 지정할 수 있습니다. 반면call
함수에 인수를 직접 지정할 수 있습니다. 모두apply
와call
즉시 지정된 컨텍스트에서 지정된 인수와 함께 함수를 호출합니다. 반면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. this
ES6 화살표 기능
화살표 함수에서 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
답변
자바 스크립트 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
있습니다.
객체에서 함수 호출
이를 수행하는 다른 방법이 있습니다. forEach
and와 같은 Javascript에서 원시 메소드를 호출 한 경우, 해당 경우 변수가 해당 함수를 호출 한 것을 참조한다는 slice
것을 이미 알고 있어야 합니다 (javascript에서는 거의 모든 것이 s 및 s를 포함하여 ). 예를 들어 다음 코드를 사용하십시오.this
Object
Object
Array
Function
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
키워드를 사용할 때 어떤 일이 발생하는지 봅시다 .
new
키워드로 함수를 호출하면Object
의 유형 이 즉시 초기화Person
됩니다.- 이 생성자는
Object
생성자를로 설정했습니다Person
. 또한typeof awal
반환Object
만합니다. - 이 새로운 것에
Object
는의 프로토 타입이 할당됩니다Person.prototype
.Person
이는를Person
포함하여의 모든 인스턴스 에서 프로토 타입의 모든 메소드 또는 속성을 사용할 수 있음을 의미합니다awal
. - 함수
Person
자체가 이제 호출됩니다.this
새롭게 구성된 객체에 대한 참조awal
입니다.
아주 간단합니까?
공식 ECMAScript 사양에는 이러한 유형의 기능이 실제 constructor
기능 이라고 명시되어 있지 않습니다. 그것들은 단지 정상적인 기능이며 new
모든 기능에서 사용될 수 있습니다. 단지 우리가 그것들을 그대로 사용하는 것 뿐이므로, 그것들을 그렇게 만 부릅니다.
함수에서 함수 호출 : call
및apply
그래서 그래, 이후 function
의도 있습니다Objects
(그리고 실제로 Javascript의 첫 번째 클래스 변수이기 때문에) 함수조차도 함수 자체가 있습니다.
모든 기능은 세계에서 상속 Function
, 그 많은 방법이 있습니다 call
와 apply
, 둘 다의 값을 조작하는 데 사용할 수있는 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
모든 함수에서 입니다.
apply
call
두 개의 매개 변수 만 사용한다는 점 과 거의 동일 thisArg
합니다. 함수에 전달할 인수가 포함 된 배열입니다. 따라서 위의 call
호출은 다음 apply
과 같이 번역 될 수 있습니다 .
foo.apply(thisArg, [1,2,3])
그 주 call
와 apply
의 값을 대체 할 수 있습니다this
우리 번째 탄환에서 설명한 도트 메소드 호출에 의해 설정한다. 충분히 간단하다 🙂
발표 …. bind
!
bind
의 형제 call
와 apply
. 또한 Function
Javascript 의 전역 생성자에서 모든 함수에 의해 상속되는 메소드 입니다. 차이 bind
및 call
/ apply
그 모두 인 call
및 apply
것 실제로 기능을 호출한다. bind
반면에는 thisArg
및 arguments
사전 설정을 사용하여 새 함수를 반환합니다 . 이것을 더 잘 이해하기 위해 예를 들어 봅시다.
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
원래 범위에서 값을 원했습니다 . 우리가 ‘복사’그래서 this
에 that
사용 된 대신의 복사this
. 영리한가?
인덱스:
- 개최 내용
this
기본적으로 됩니까? - 객체 점 표기법을 사용하여 함수를 함수로 호출하면 어떻게됩니까?
- 우리가
new
키워드를 어떻게 되나요? - 우리는 어떻게 조작 할
this
로call
와apply
? - 사용
bind
. this
중첩 된 범위 문제를 해결하기위한 복사
답변
“이것”은 범위에 관한 것입니다. 모든 함수에는 고유 한 범위가 있으며 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);
사용해보십시오. 이 프로그래밍 패턴을 좋아하기 시작합니다
답변
이 글타래가 엉망이되어서, 나는 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) 우리가 사용하는 그 방법 빌리 : this
2)는 우리가 사용하는 방법을 지정 this
변수, 3) 함수가 사용가 this
4 콜백 함수로 전달되고,이) 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)
참고 문헌 :
- Kyle & Simpson의 this & Object Prototypes © 2014 Getify 솔루션.
- javascriptissexy.com- http : //goo.gl/pvl0GX
- 앵거스 크롤 – http://goo.gl/Z2RacU
답변
this
JavaScript에서 항상 실행중인 함수의 ‘소유자’를 나타냅니다 .
명시 적 소유자가 정의되지 않은 경우 최상위 소유자 인 창 개체가 참조됩니다.
내가 한 경우
function someKindOfFunction() {
this.style = 'foo';
}
element.onclick = someKindOfFunction;
this
요소 객체를 참조합니다. 그러나 많은 사람들이이 실수를 저 지르십시오.
<element onclick="someKindOfFunction()">
후자의 경우, 함수를 요소에 넘기는 것이 아니라 함수를 참조 할뿐입니다. 따라서 this
창 개체를 참조합니다.
답변
자바 스크립트의 모든 실행 컨텍스트 에는 다음에 의해 설정된 this 매개 변수가 있습니다.
- 함수 호출 방법 (오브젝트 메소드, 호출 및 적용 사용, new 사용 포함 )
- 바인드 사용
- 어휘 화살표 기능 (그들이 채택 이 그 외측의 실행 컨텍스트를)
- 코드가 엄격 또는 비 엄격 모드인지 여부
- 코드를 사용하여 호출했는지 여부
eval
당신의 값을 설정할 수 있습니다 이 사용을 func.call
, func.apply
또는 func.bind
.
기본적으로 대부분의 초보자를 혼란스럽게 만드는 요소는 DOM 요소에서 이벤트가 발생한 후 리스너가 호출 될 때 함수 의이 값은 DOM 요소입니다.
jQuery는 jQuery.proxy로이 사소한 변경을 만듭니다.