this
키워드가 무엇인지, 그리고 이것이 스택 오버플로 사이트의 JavaScript에서 올바르게(그리고 잘못) 어떻게 사용되는지에 대한 명확한 설명이 없는 것으로 보입니다.
나는 매우 이상한 행동을 목격했으며 왜 그것이 발생했는지 이해하지 못했습니다.
this
어떻게 작동하며 언제 사용해야 합니까?
질문자 :Maxim Gershkovich
this
키워드가 무엇인지, 그리고 이것이 스택 오버플로 사이트의 JavaScript에서 올바르게(그리고 잘못) 어떻게 사용되는지에 대한 명확한 설명이 없는 것으로 보입니다.
나는 매우 이상한 행동을 목격했으며 왜 그것이 발생했는지 이해하지 못했습니다.
this
어떻게 작동하며 언제 사용해야 합니까?
this
실행 컨텍스트의 속성인 JavaScript의 키워드입니다. 주요 용도는 함수와 생성자입니다.
Mike West 의 기사 Scope in JavaScript ( archived )를 먼저 읽는 것이 좋습니다. this
와 scope chains의 개념에 대한 훌륭하고 친근한 소개입니다. 에 대한 규칙 this
(당신이 모범 사례에 충실 경우) 매우 간단합니다.
this
명세서의 ECMAScript 표준 은 ResolveThisBinding 추상 작업을 통해 이를 this
.
추상적 동작은 ResolveThisBinding [...] 상기 키워드의 결합 판정
this
의 LexicalEnvironment하여 실행하는 실행 콘텍스트 . 호출 시 다음 단계를 수행합니다.
- envRec 를 GetThisEnvironment ()로 설정합니다.
- 반품 ? envRec .GetThisBinding().
전역 환경 레코드 , 모듈 환경 레코드 및 기능 환경 레코드 에는 각각 고유한 GetThisBinding 메서드가 있습니다.
GetThisEnvironment 추상적 인 작업은 현재 찾아 실행중인 실행 컨텍스트 의 LexicalEnvironment을하고,이 바인딩 (즉 HasThisBinding 반환 true)를 가지고있는 (반복적으로 자신의 [[OuterEnv]] 속성에 액세스하여) 가장 가까운 상승 환경 기록을 찾습니다. 이 프로세스는 세 가지 환경 레코드 유형 중 하나로 끝납니다.
의 값 this
종종 코드에 있는지 여부에 따라 엄격 모드 .
GetThisBinding의 반환 값 반영 값 this
현재 실행 컨텍스트를 그래서 새로운 실행 컨텍스트가 설정 될 때마다, this
고유 값으로 해결한다. 이는 현재 실행 컨텍스트가 수정될 때도 발생할 수 있습니다. 다음 하위 섹션에서는 이러한 일이 발생할 수 있는 5가지 경우를 나열합니다.
사양 세부 정보와 함께 따르기 위해 AST 탐색기 에 코드 샘플을 넣을 수 있습니다.
이것은 최상위 수준에서 평가되는 스크립트 코드입니다(예: <script>
<script> // Global context console.log(this); // Logs global object. setTimeout(function(){ console.log("Not global context"); }); </script>
스크립트의 초기 전역 실행 컨텍스트에서 이를 평가하면 GetThisBinding this
다음 단계를 수행합니다.
전역 환경 레코드 envRec […]의 GetThisBinding 구체적인 메서드는 호출될 때 다음 단계를 수행합니다.
- envRec .[[GlobalThisValue]]를 반환합니다.
전역 환경 레코드의 [[GlobalThisValue]] 속성은 항상 호스트 정의 전역 개체로 globalThis
( 웹의 window
, Node.js의 global
, MDN의 문서)를 통해 도달할 수 있습니다. InitializeHostDefinedRealm 의 단계에 따라 [[GlobalThisValue]] 속성이 어떻게 되는지 알아보세요.
모듈은 ECMAScript 2015에 도입되었습니다.
이것은 모듈에 적용됩니다. 예를 들어, 단순한 <script>
<script type="module">
내부에 직접 있을 때입니다.
모듈의 초기 전역 실행 컨텍스트에서 이를 평가하면 GetThisBinding this
다음 단계를 수행합니다.
모듈 환경 레코드 [...]의 GetThisBinding 구체적인 메서드는 호출될 때 다음 단계를 수행합니다.
- undefined 를 반환합니다.
맞습니다. 모듈에서 this
값은 전역 컨텍스트에서 항상 undefined
모듈은 암시적으로 엄격 모드에 있습니다.
eval
호출에는 직접 및 간접 의 두 가지 종류가 있습니다. 이러한 구분은 ECMAScript 5판부터 존재합니다.
eval
호출은 일반적으로 eval(
… );
또는 (eval)(
… );
(또는 ((eval))(
… );
등). 1 호출 표현식이 좁은 패턴에 맞는 경우에만 직접적입니다. 2eval
호출에는 다른 방식으로 eval
를 호출하는 것이 포함됩니다. eval?.(
… )
, (
… , eval)(
… )
, window.eval(
… )
, eval.call(
… ,
… )
등이 될 수 있습니다. const aliasEval1 = eval; window.aliasEval2 = eval;
, aliasEval1(
… )
, aliasEval2(
… )
됩니다. 별도로 주어진 const originalEval = eval; window.eval = (x) => originalEval(x);
eval(
… )
호출하는 것도 간접적입니다. "(1, eval)('this') vs eval('this') in JavaScript?"에 대한 chuckj의 답변을 참조하십시오. 및 Dmitry Soshnikov의 ECMA-262-5 세부 정보 – 2장: eval()
호출을 사용할 수 있는 경우에 대한 엄격한 모드( 아카이브됨).
PerformEval eval
코드를 실행합니다. GetThisEnvironment this
값을 가져오는 LexicalEnvironment로 새 선언적 환경 레코드를 만듭니다.
경우, this
나타납니다가의 eval
코드, 환경 기록의 GetThisBinding 방법에 의해 발견 GetThisEnvironment 라는 그 값이 반환됩니다.
그리고 생성된 선언적 환경 레코드 eval
호출이 직접인지 간접인지에 따라 달라집니다.
이는 다음을 의미합니다.
this
값은 변경되지 않습니다. eval
이라는 어휘 범위에서 가져왔습니다.this
값은 전역 객체( globalThis
)입니다. new Function
어떻습니까? — new Function
eval
과 유사하지만 코드를 즉시 호출하지 않습니다. 함수를 생성합니다. 이 바인딩은 다음 하위 섹션에 설명된 대로 정상적으로 작동하는 함수가 호출될 때를 제외하고 여기 어디에도 적용되지 않습니다.
함수 코드 입력은 함수를 호출 할 때 발생합니다.
함수를 호출하는 구문에는 네 가지 범주가 있습니다.
실제 함수 호출은 컨텍스트에서 결정된 thisValue 로 호출되는 Call 추상 작업에서 발생합니다. 이 인수는 호출 관련 호출의 긴 체인으로 전달됩니다. Call 은 함수의 [[Call]] 내부 슬롯을 호출합니다. 이것은 새 함수 환경 레코드 가 생성 되는 PrepareForOrdinaryCall을 호출합니다.
함수 환경 레코드 는 함수의 최상위 범위를 나타내는 데 사용되는 선언적 환경 레코드이며 함수가 ArrowFunction
this
바인딩을 제공합니다. 함수가 ArrowFunction 함수가 아니고super
참조하는 경우 함수 환경 레코드에는 함수 내에서super
메소드 호출을 수행하는 데 사용되는 상태도 포함됩니다.
또한 함수 환경 레코드에는 [[ThisValue]] 필드가 있습니다.
이것은 이 함수 호출에 사용되는
this
NewFunctionEnvironment 호출은 함수 환경의 [[ThisBindingStatus]] 속성도 설정합니다.
[[Call]] 은 다음을 기반으로 적절한 thisArgument 가 결정되는 OrdinaryCallBindThis 도 호출합니다.
결정되면, 호출에 대한 최종 BindThisValue의 새로 만든 함수 환경 기록 방법은 실제로 thisArgument로 [ThisValue] 필드를 설정한다.
마지막으로 이 필드는 Environment Record의 GetThisBinding this
에서 이에 대한 값을 가져오는 곳입니다.
함수 환경 레코드 envRec […]의 GetThisBinding 구체적인 메서드는 호출될 때 다음 단계를 수행합니다.
[…]
3. envRec .[[ThisValue]]를 반환합니다.
다시 말하지만, 이 값이 얼마나 정확하게 결정되는지는 많은 요인에 따라 다릅니다. 이것은 단지 일반적인 개요였습니다. 이러한 기술적 배경을 바탕으로 모든 구체적인 예를 살펴보겠습니다.
화살표 함수 가 평가될 때 함수 개체의 [[ThisMode]] 내부 슬롯은 OrdinaryFunctionCreate 에서 "lexical" 로 설정됩니다.
함수 F 를 취하는 OrdinaryCallBindThis 에서:
- thisMode 를 F .[[ThisMode]]로 설정합니다.
- thisMode 가 lexical 이면 NormalCompletion(
undefined
)을 반환합니다. […]
이 결합하는 알고리즘의 나머지를 스킵 것을 단지 의미. 화살표 함수는 자체 this 값을 바인딩하지 않습니다.
그렇다면 화살표 함수 안에 있는 this
ResolveThisBinding 및 GetThisEnvironment를 다시 살펴보면 HasThisBinding 메서드가 명시적으로 false를 반환합니다.
환경 레코드 envRec […] 함수의 HasThisBinding 구체적인 메서드는 호출될 때 다음 단계를 수행합니다.
- envRec .[[ThisBindingStatus]] 가 어휘 이면 false 를 반환합니다. 그렇지 않으면 true 를 반환합니다.
따라서 외부 환경은 대신 반복적으로 조회됩니다. 이 바인딩이 있는 세 가지 환경 중 하나에서 프로세스가 종료됩니다.
것을이 단지 수단 this
어휘 화살표 기능 기관에서 결정된다, 또는 다른 말로 (에서 함수 선언 / 표현 대 화살표 기능 : 그들은 동등 / 교환이 있습니까? )
화살표 함수에는 고유한
this
[...] 바인딩이 없습니다. 대신 [이 식별자는] 다른 변수와 마찬가지로 어휘 범위에서 확인됩니다. 화살표 함수 내 것을 그 수단this
에서 [의 값 [의미]this
환경에서 화살표 함수 (즉, "외부"화살표 함수)에 정의되어있다].
일반 함수( function
, methods )에서 this
함수가 호출되는 방식에 따라 결정됩니다.
여기에서 이러한 "구문 변형"이 유용합니다.
함수를 포함하는 다음 객체를 고려하십시오.
const refObj = { func: function(){ console.log(this); } };
또는:
const refObj = { func(){ console.log(this); } };
다음 함수 호출에서 func
내부 this
값은 refObj
됩니다. 1
refObj.func()
refObj["func"]()
refObj?.func()
refObj.func?.()
refObj.func``
호출된 함수가 구문상 기본 개체의 속성인 경우 이 기본은 호출의 "참조"가 되며 일반적으로 this
의 값이 됩니다. 이것은 위에 링크된 평가 단계에 의해 설명됩니다. 예를 들어, refObj.func()
(또는 refObj["func"]()
)에서 CallMemberExpression 은 MemberExpression refObj.func
및 Arguments ()
로 구성된 전체 표현식 refObj.func()
() 입니다.
그러나 또한 refObj.func
및 refObj
는 각각 다음과 같은 세 가지 역할을 합니다.
값으로 refObj.func
는 호출 가능한 함수 객체입니다. 해당 참조 this
바인딩을 결정하는 데 사용됩니다.
옵션 체인 및 태그 템플릿 예는 매우 유사하게 작동 : 기본적으로 참조하기 전에 모든 인 ?.()
, 전 ``
, 또는 이전에 ()
.
EvaluateCall 은 해당 참조의 IsPropertyReference 를 사용하여 구문적으로 개체의 속성인지 확인합니다. 참조의 [[Base]] 속성(예: refObj
에 적용될 때 refObj.func
, 또는 foo.bar.baz
적용될 때 foo.bar
속성을 얻으려고 합니다. 속성으로 작성된 경우 GetThisValue 는 이 [[Base]] 속성 을 가져와 this 값으로 사용합니다.
참고: Getters/Setters this
관련하여 메서드와 동일한 방식으로 작동합니다. 간단한 속성, 실행 컨텍스트에 영향을 미치지 여기 예하지 않는, this
전역 범위에 있습니다 :
const o = { a: 1, b: this.a // Is `globalThis.a`. };
with
기본 참조가 없는 호출은 일반적으로 속성으로 호출되지 않는 함수입니다. 예를 들어:
func(); // As opposed to `refObj.func();`.
이것은 메서드를 전달하거나 할당 하거나 쉼표 연산자를 사용할 때도 발생합니다. 여기에서 참조 레코드와 값의 차이가 관련됩니다.
const g = (f) => f(); // No base ref. const h = refObj.func; g(refObj.func); h(); // No base ref. (0, refObj.func)(); // Another common pattern to remove the base ref.
EvaluateCall 은 여기서 정의되지 않은 thisValue 로 Call 을 호출합니다. 이 차이하게 OrdinaryCallBindThis (F : 함수 객체; thisArgument을 다음 thisValue가 전달 통화 )
- thisMode 를 F .[[ThisMode]]로 설정합니다.
[…]
- thisMode가 strict 이면 thisValue를 thisArgument 로 설정 합니다.
- 또 다른,
[…]
참고: 5단계에서는 this
의 실제 값을 엄격 모드에서 제공된 thisArgument 로 설정합니다(이 경우 undefined
"조잡한 모드"에서 정의되지 않았거나 null thisArgument 는 this
가 전역 this 값이 되도록 합니다.
IsPropertyReference 가 false 를 반환하면 EvaluateCall 은 다음 단계를 수행합니다.
- refEnv 를 ref .[[Base]]로 설정합니다.
- 주장: refEnv 는 환경 레코드입니다.
- thisValue 를 refEnv .WithBaseObject()로 설정합니다.
정의되지 않은 thisValue가에서 올 수있는 곳이다 : refEnv. WithBaseObject () 는 with
문을 제외하고 항상 undefined 입니다. 이 경우 thisValue 는 바인딩 객체가 됩니다.
도 있습니다 Symbol.unscopables
( MDN에 문서 을 제어하는) with
동작을 결합.
지금까지 요약하자면 다음과 같습니다.
function f1(){ console.log(this); } function f2(){ console.log(this); } function f3(){ console.log(this); } const o = { f1, f2, [symbol.unscopables]: { f2: true } }; f1(); // Logs `globalThis`. with(o){ f1(); // Logs `o`. f2(); // `f2` is unscopable, so this logs `globalThis`. f3(); // `f3` is not on `o`, so this logs `globalThis`. }
그리고:
"use strict"; function f(){ console.log(this); } f(); // Logs `undefined`. // `with` statements are not allowed in strict-mode code.
this
평가할 때 일반 함수가 정의된 위치 는 중요하지 않습니다 .
.call
, .apply
, .bind
, thisArg 및 프리미티브6.2단계(사양의 6.b)와 함께 OrdinaryCallBindThis 의 5단계의 또 다른 결과는 기본 this 값이 "조잡한" 모드 에서만 객체로 강제 변환된다는 것입니다.
바인딩이 메소드를 오버라이드 (override)하는 세 가지 방법 :이 문제를 조사하기 위해,하자의는이 값에 대한 다른 소스를 소개 4
Function.prototype.apply(thisArg, argArray)
Function.prototype.
{ call
, bind
} (thisArg, ...args)
.bind
는 이 바인딩이 thisArg 로 설정되고 다시 변경할 수 없는 바인딩된 함수를 만듭니다. .call
및 .apply
thisArg에이 결합 세트 바로 함수를 호출한다.
.call
및 .apply
에 직접 매핑 통화 지정된 thisArg를 사용. .bind
사용하여 바인딩된 함수를 만듭니다 . 여기에는 함수 개체의 [[BoundThis]] 내부 슬롯을 조회하는 자체 [[Call]] 메서드가 있습니다.
사용자 정의 이 값을 설정하는 예:
function f(){ console.log(this); } const myObj = {}, g = f.bind(myObj), h = (m) => m(); // All of these log `myObj`. g(); f.bind(myObj)(); f.call(myObj); h(g);
객체의 경우 엄격 모드와 비엄격 모드에서 동일합니다.
이제 기본 값을 제공하십시오.
function f(){ console.log(this); } const myString = "s", g = f.bind(myString); g(); // Logs `String { "s" }`. f.call(myString); // Logs `String { "s" }`.
비엄격 모드에서 프리미티브는 객체 래핑 형식으로 강제 변환됩니다. Object("s")
또는 new String("s")
호출할 때 얻는 것과 같은 종류의 객체입니다. 엄격 모드에서는 다음과 같은 프리미티브를 사용할 수 있습니다.
"use strict"; function f(){ console.log(this); } const myString = "s", g = f.bind(myString); g(); // Logs `"s"`. f.call(myString); // Logs `"s"`.
라이브러리는 이러한 메서드를 사용합니다. 예를 들어 jQuery는 this
를 여기에서 선택한 DOM 요소로 설정합니다.
$("button").click(function(){ console.log(this); // Logs the clicked button. });
new
new
연산자를 사용하여 함수를 생성자로 호출할 때 EvaluateNew 는 [[Construct]] 메서드 를 호출하는 Construct 를 호출합니다. 함수가 기본 생성자(즉, class extends
… {
… }
아님)인 경우 thisArgument 를 생성자의 프로토타입에서 생성된 새 객체로 설정합니다. this
에 설정된 속성은 결과 인스턴스 개체에서 끝납니다. this
암시 적으로 명시 적으로 자신이 아닌 프리미티브 값을 반환하지 않는 한 반환됩니다.
class
는 ECMAScript 2015에 도입된 생성자 함수를 생성하는 새로운 방법입니다.
function Old(a){ this.p = a; } const o = new Old(1); console.log(o); // Logs `Old { p: 1 }`. class New{ constructor(a){ this.p = a; } } const n = new New(1); console.log(n); // Logs `New { p: 1 }`.
클래스 정의는 암시적으로 엄격 모드에 있습니다 .
class A{ m1(){ return this; } m2(){ const m1 = this.m1; console.log(m1()); } } new A().m2(); // Logs `undefined`.
super
new
를 사용한 동작의 예외는 위에서 언급한 대로 class extends
… {
… }
파생 클래스는 호출 시 this 값을 즉시 설정하지 않습니다. super
호출 이후에만 그렇게 constructor
없이 암시적으로 발생). super
를 호출하기 전에 this
사용하는 것은 허용되지 않습니다.
super
호출하면 호출의 어휘 범위(함수 환경 레코드)의 this 값을 사용하여 수퍼 생성자를 호출합니다. GetThisValue super
호출에 대한 특별한 규칙이 있습니다. BindThisValue 를 사용 this
이를 해당 환경 레코드로 설정합니다.
class DerivedNew extends New{ constructor(a, a2){ // Using `this` before `super` results in a ReferenceError. super(a); this.p2 = a2; } } const n2 = new DerivedNew(1, 2); console.log(n2); // Logs `DerivedNew { p: 1, p2: 2 }`.
인스턴스 필드와 정적 필드는 ECMAScript 2022에서 도입되었습니다.
class
가 평가되면 실행 중인 실행 컨텍스트를 수정하는 ClassDefinitionEvaluation 이 수행됩니다. 각 ClassElement에 대해:
this
클래스 자체를 참조하고,this
인스턴스를 지칭한다. 개인 필드(예: #x
) 및 메소드가 PrivateEnvironment에 추가됩니다.
정적 블록 은 현재 TC39 3단계 제안 입니다. 정적 블록은 정적 필드 및 메서드와 동일하게 작동합니다. this
블록 내부는 클래스 자체를 참조합니다.
메소드 및 getter/setter에서 this
일반 함수 속성과 동일하게 작동합니다.
class Demo{ a = this; b(){ return this; } static c = this; static d(){ return this; } // Getters, setters, private modifiers are also possible. } const demo = new Demo; console.log(demo.a, demo.b()); // Both of them log `demo`. console.log(Demo.c, Demo.d()); // Both of them log `Demo`.
1 : (of)()
of()
와 정확히 동일합니다. (f)()
f()
와 정확히 동일합니다. 이것은 이 2ality 기사 ( 아카이브됨 )에 설명되어 있습니다. 특히 ParentheisedExpression 이 어떻게 평가되는지 확인하십시오.
2 : MemberExpression 이어야 하고, 속성이 아니어야 하며, 정확히 "eval" 인 [[ReferencedName]]이(가) 있어야 하며, %eval% 내장 개체여야 합니다.
3 : 사양에 " 참조를 X 를 평가한 결과로 지정합니다. "라고 표시될 때마다 X 는 평가 단계를 찾아야 하는 일부 표현입니다. 예를 들어 MemberExpression 또는 CallExpression 평가는 이러한 알고리즘 중 하나의 결과입니다. 그들 중 일부는 참조 레코드를 생성 합니다.
4 : 이 값을 제공할 수 있는 몇 가지 다른 기본 및 호스트 메서드가 있습니다 . 특히 thisArg 를 두 번째 인수로 허용하는 Array.prototype.map
, Array.prototype.forEach
사람은 변경하는 자신의 방법을 만들 수있다 this
같은 (func, thisArg) => func.bind(thisArg)
, (func, thisArg) => func.call(thisArg)
, 항상 등, MDN의 제공 훌륭한 문서.
각 코드 조각에 대해 다음 질문에 답하십시오. “표시된 줄에서 this
값은 얼마입니까? 왜?" .
답변을 표시하려면 회색 상자를 클릭하십시오.
if(true){ console.log(this); // What is `this` here? }
globalThis
. 표시된 라인은 초기 전역 실행 컨텍스트에서 평가됩니다.
const obj = {}; function myFun(){ return { // What is `this` here? "is obj": this === obj, "is globalThis": this === globalThis }; } obj.method = myFun; console.log(obj.method());
obj
. 객체의 속성으로 함수를 호출할 때 this 바인딩을 참조 obj.method 의 기본obj.method
(예:obj
.
const obj = { myMethod: function(){ return { // What is `this` here? "is obj": this === obj, "is globalThis": this === globalThis }; } }, myFun = obj.myMethod; console.log(myFun());
globalThis
. 함수 값myFun
/obj.myMethod
는 객체에서 호출되지 않으므로 속성으로 이 바인딩은globalThis
입니다.obj.myMethod
)에 액세스하면 바인딩된 메서드 개체 가 생성되는 Python과 다릅니다.
const obj = { myFun: () => ({ // What is `this` here? "is obj": this === obj, "is globalThis": this === globalThis }) }; console.log(obj.myFun());
globalThis
. 화살표 함수는 이 바인딩을 자체적으로 생성하지 않습니다. 그래서 어휘 범위는 초기 글로벌 범위와 동일this
있다globalThis
.
function myFun(){ console.log(this); // What is `this` here? } const obj = { myMethod: function(){ eval("myFun()"); } }; obj.myMethod();
globalThis
. 직접 평가 호출을 평가할 때this
obj
입니다. 그러나 평가 코드에서myFun
은 개체에서 호출되지 않으므로 이 바인딩은 전역 개체로 설정됩니다.
function myFun() { // What is `this` here? return { "is obj": this === obj, "is globalThis": this === globalThis }; } const obj = {}; console.log(myFun.call(obj));
obj
. 라인myFun.call(obj);
thisArg
를 첫 번째 인수로 받아들이는 특별한 내장 함수Function.prototype.call
class MyCls{ arrow = () => ({ // What is `this` here? "is MyCls": this === MyCls, "is globalThis": this === globalThis, "is instance": this instanceof MyCls }); } console.log(new MyCls().arrow());
MyCls
의 인스턴스입니다. 화살표 함수는 이 바인딩을 변경하지 않으므로 이 바인딩은 사전적으로 결정됩니다. 따라서 이것은a = this;
와 같이 위에서 언급한 클래스 필드와 정확히 동일합니다. .static arrow
변경해 보십시오. 기대한 결과를 얻었습니까?
this
키워드는 JavaScript에서 다른 언어와 다르게 동작합니다. 객체 지향 언어에서 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
연산자를 사용하여 인스턴스를 생성해야 할 수도 있습니다. 나는 우리가 객체와 함께했던 것을 모든 것들을 밖으로 시도 아래 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])
설정 obj1
의 값 this
내부의 fun()
및 통화 fun()
의 요소를 전달 argsArray
인수한다.fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])
- obj1
fun()
내부 this
값으로 arg1, arg2, arg3, ...
전달하는 fun()
을 호출합니다. arg1, arg2, arg3, ...
의 인수로.fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])
this
내부 fun obj1
fun
의 매개 변수가 arg1, arg2, arg3,...
지정된 매개 변수에 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 = // `oa` ie 4 + 5 + 6 = 15 document.write(add.apply(o, [5, 6]) + "<br />"); //15 // `oa` ie 4 + 5 + 6 = 15 var g = add.bind(o, 5, 6); //g: `oa` ie 4 + 5 + 6 document.write(g()+"<br />"); //15 var h = add.bind(o, 5); //h: `oa` ie 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
과 같은 전통적인 이벤트 등록 메소드를 통해 수행할 수 있습니다.<button onclick="...this..." >
this
직접 사용하면 요소를 참조합니다.this
글로벌 객체에 함수 나 이벤트 속성 결의를 처리하는 이벤트 내에서 호출 다른 기능을 통해 간접적으로 window
.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 만 기록됩니다 undefined
않았기 때문입니다.
this
값을 조작하는 방법을 볼 수 있습니다.
이를 수행하는 다양한 방법이 있습니다. forEach
및 slice
와 같은 기본 메서드를 호출한 경우 this
변수가 Object
를 참조한다는 것을 이미 알고 있어야 합니다(자바스크립트에서는 Array
포함하여 Object
및 Function
s). 다음 코드를 예로 들어 보겠습니다.
var myObj = {key: "Obj"}; myObj.logThis = function () { // I am a method console.log(this); } myObj.logThis(); // myObj is logged
Object
Function
을 보유하는 속성을 포함하는 경우 이 속성을 메서드라고 합니다. 이 메서드는 호출될 때 항상 연결된 Object
this
변수를 갖습니다. 엄격 모드와 비엄격 모드 모두에 해당됩니다.
방법은 다른 변수에 저장 (또는 오히려, 복사) 인 경우의 참조 점에 유의 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
키워드로 함수를 호출하면 Person
유형 Object
가 즉시 초기화됩니다.Object
의 생성자는 Person
설정된 생성자를 가지고 있습니다. 또한 typeof awal
은 Object
만 반환합니다.Object
Person.prototype
의 프로토타입이 할당됩니다. Person
프로토타입의 모든 메서드 또는 속성은 awal
포함하여 Person
모든 인스턴스에서 사용할 수 있습니다.Person
자체 함수가 호출됩니다. this
새로 생성된 객체 awal
에 대한 참조입니다.꽤 간단하죠?
공식 ECMAScript 사양에는 그러한 유형의 함수가 실제 constructor
함수라고 명시되어 있지 않습니다. 그것들은 그냥 일반적인 함수이고 new
는 어떤 함수에도 사용될 수 있습니다. 단지 우리가 그것들을 그대로 사용하고, 그래서 우리는 그것들을 그렇게만 부르는 것뿐입니다.
call
: 호출 및 apply
네, function
s도 Objects
이기 때문에(사실 자바스크립트의 일급 변수), 심지어 함수에도... 음, 함수 자체인 메소드가 있습니다.
모든 함수는 전역 Function
에서 상속되며 많은 메서드 중 두 가지가 call
및 apply
이며 둘 다 호출되는 함수에서 this
값을 조작하는 데 사용할 수 있습니다.
function foo () { console.log (this, arguments); } var thisArg = {myObj: "is cool"}; foo.call(thisArg, 1, 2, 3);
call
을 사용하는 전형적인 예입니다. 기본적으로 첫 번째 매개변수를 취하여 foo
함수 thisArg
대한 참조로 this
. call
에 전달된 다른 모든 매개변수는 foo
함수에 인수로 전달됩니다.
따라서 위의 코드는 {myObj: "is cool"}, [1, 2, 3]
을 기록합니다. 모든 함수에서 this
값을 변경하는 아주 좋은 방법입니다.
apply
thisArg
와 함수에 전달할 인수가 포함된 배열이라는 두 개의 매개변수만 사용한다는 점에서 call
accept와 거의 동일합니다. 따라서 위의 call
호출은 다음과 같이 apply
되도록 번역될 수 있습니다.
foo.apply(thisArg, [1,2,3])
call
및 apply
은 두 번째 글머리 기호에서 논의한 점 메서드 호출 this
집합의 값을 재정의할 수 있습니다. 충분히 간단합니다 :)
bind
! bind
call
and apply
의 형제입니다. Function
생성자에서 모든 함수가 상속하는 메서드입니다. 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.value = 값; $('.some-elements').each(function(elt){ elt.innerHTML = this.value; // 어 오!! 아마도 정의되지 않은 }); })(2);
따라서 여기 each() 내부에서 "this"는 예상한 "값"을 보유하지 않습니다(from
this.value = 값;그 위에). 따라서 이(말장난 의도 없음) 문제를 극복하기 위해 개발자는 다음을 수행할 수 있습니다.
(함수(값) { var 자기 = 이것; // 작은 변화 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
키워드는 this
를 사용하는 메서드를 빌릴 때 this
사용하는 메서드를 변수에 할당할 때, 3) this
사용하는 함수가 콜백 함수로 전달될 때, 4) this
가 다음과 같은 경우에 가장 잘못 이해됩니다. 클로저 내부에서 사용 - 내부 함수. (2)
ECMA 스크립트 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)
참조:
this
는 항상 실행 중인 함수의 '소유자'를 나타냅니다.
명시적 소유자가 정의되지 않은 경우 최상위 소유자인 창 개체가 참조됩니다.
그래서 내가 그랬다면
function someKindOfFunction() { this.style = 'foo'; }
element.onclick = someKindOfFunction;
this
요소 개체를 참조합니다. 하지만 조심하세요. 많은 사람들이 이런 실수를 합니다.
<element onclick="someKindOfFunction()">
후자의 경우 요소에 전달하지 않고 함수를 참조하기만 하면 됩니다. 따라서 this
창 개체를 참조합니다.
자바스크립트의 모든 실행 컨텍스트 에는 다음과 같이 설정되는 this 매개변수가 있습니다.
eval
사용하여 호출되었는지 여부 func.call
, func.apply
또는 func.bind
사용하여 이 값을 설정할 수 있습니다.
기본적으로 대부분의 초보자를 혼란스럽게 하는 것은 DOM 요소에서 이벤트가 발생한 후 리스너가 호출될 때 함수의 this 값이 DOM 요소입니다.
jQuery는 이것을 jQuery.proxy로 변경하는 것을 간단하게 만듭니다.
다니엘, 멋진 설명! 이벤트 핸들러의 경우 this
실행 컨텍스트 포인터의 좋은 목록과 이것에 대한 몇 마디.
두 단어로 말하자면, this
는 현재 함수가 실행된 개체(또는 실행 컨텍스트에서)를 가리키며 항상 읽기 전용이므로 어쨌든 설정할 수 없습니다(이러한 시도는 'Invalid left- 과제에 손을 대십시오'라는 메시지가 표시됩니다.
이벤트 핸들러의 경우: <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)">
여기에 하나의 좋은 소스입니다 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"
repl을 사용하는 node
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
제공 노드와 사용한 브라우저 모두 (더 아래 참조) this
함께 호출되지 않는 기능에 new
전역 참조 ...
<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>
new
this
로 함수를 호출하면 새 컨텍스트가 되고 전역 this
참조하지 않습니다.
<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"
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 속성, 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는 많은 곳에서 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>
JavaScript에서 "this" 키워드가 해석되는 방식에 대해 많은 혼란이 있습니다. 바라건대 이 기사는 모든 사람들이 한 번에 쉬게 해주기를 바랍니다. 그리고 훨씬 더. 전체 기사를 주의 깊게 읽으십시오. 글이 깁니다.
사용되는 컨텍스트에 관계없이 "this"는 항상 Javascript에서 "현재 개체" 를 참조합니다. 그러나 "현재 개체" 가 무엇인지는 컨텍스트 에 따라 다릅니다. 컨텍스트 는 다음 6개 중 정확히 1개일 수 있습니다.
다음은 이러한 각 컨텍스트를 하나씩 설명합니다.
전역 컨텍스트 (즉, 모든 기능 외부):
모든 기능 외부(즉, 전역 컨텍스트에서) "현재 개체" (따라서 "this" 값)는 항상 브라우저의 "창" 개체입니다.
내부 직접 "비결합 함수" 호출 :
직접 "비 바인딩된 함수" 호출 내에서 함수 호출을 호출한 개체는 "현재 개체" (따라서 "this" 값)가 됩니다. 명시적인 현재 객체 없이 함수가 호출되면 현재 객체 는 "창" 객체(비 엄격 모드의 경우) 또는 정의되지 않은 (엄격한 모드의 경우) 입니다. 전역 컨텍스트에 정의된 모든 함수(또는 변수)는 자동으로 "창" 개체의 속성이 됩니다. 예를 들어 전역 컨텍스트에서 함수가 다음과 같이 정의된다고 가정합니다.
function UserDefinedFunction(){ alert(this) }
마치 다음과 같이 정의한 것처럼 창 개체의 속성이 됩니다.
window.UserDefinedFunction=function(){ alert(this) }
"Non Strict Mode"에서 "UserDefinedFunction()"을 통해 직접 이 함수를 호출/호출하면 자동으로 "window.UserDefinedFunction()" 으로 호출/호출하여 "window" 를 "현재 개체"로 만듭니다 (따라서 " this" ) "UserDefinedFunction" 내 . "Non Strict Mode"에서 이 함수를 호출하면 다음이 발생합니다.
UserDefinedFunction() // displays [object Window] as it automatically gets invoked as window.UserDefinedFunction()
"엄격한 모드"에서 "UserDefinedFunction()"을 통해 직접 함수를 호출/호출하면 자동으로 "window.UserDefinedFunction()" 으로 호출/호출 되지 않습니다. 따라서 "현재 개체" (및 "this"의 값 ) "UserDefinedFunction" 내에서 정의되지 않습니다 . "Strict Mode"에서 이 함수를 호출하면 다음과 같은 결과가 나타납니다.
UserDefinedFunction() // displays undefined
그러나 창 개체를 사용하여 명시적으로 호출하면 다음과 같은 결과가 발생합니다.
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를 통해 호출되면 "this" 는 o2의 값을 취하고 속성 "c" 및 "d"의 값이 표시됩니다. "a" 및 "b" 값은 o2 와 마찬가지로 정의되지 않은 것으로 표시되었습니다. 이러한 속성을 정의하지 마십시오.
functionName.call 및 functionName.apply를 통한 간접 "비바운드 함수" 호출 내부 :
"비결합 함수" 가 functionName.call 또는 functionName.apply를 통해 호출되면 "현재 객체" (따라서 "this" 값)가 호출에 전달된 "this" 매개변수(첫 번째 매개변수)의 값으로 설정됩니다. / 적용 . 다음 코드는 동일한 것을 보여줍니다.
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를 통해 변경될 수 있음을 명확하게 보여줍니다. 또한 "this" 매개변수가 명시적으로 call/apply에 전달되지 않으면 "현재 개체" (따라서 "this" 값)가 비 엄격 모드에서 "window" 로 설정되고 엄격 모드에서 "undefined" 로 설정됩니다.
"바운드 함수" 호출 내부 (즉, 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" 값은 변경되지 않습니다. 첫 번째 bind 함수에서 설정한 값으로 그대로 유지됩니다.
"new"를 통한 객체 생성 중 :
생성자 함수 내에서 "현재 객체" (따라서 "this" 값)는 함수의 바인드 상태에 관계없이 "new"를 통해 현재 생성 중인 객체를 참조합니다. 그러나 생성자가 바인딩된 함수인 경우 바인딩된 함수에 대해 설정된 대로 미리 정의된 인수 집합으로 호출됩니다.
인라인 DOM 이벤트 핸들러 내부 :
다음 HTML 스니펫을 보십시오.
<button onclick='this.style.color=white'>Hello World</button> <div style='width:100px;height:100px;' onclick='OnDivClick(event,this)'>Hello World</div>
위의 예에서 "this" 는 각각 "button" 요소와 "div" 요소를 나타냅니다.
첫 번째 예에서는 버튼을 클릭할 때 버튼의 글꼴 색상을 흰색으로 설정합니다.
두 번째 예에서 "div" 요소를 클릭하면 클릭한 div 요소를 참조하는 두 번째 매개변수를 사용 하여 OnDivClick 함수를 호출합니다. 그러나 OnDivClick 내의 "this" 값은 클릭된 div 요소를 참조하지 않아야 합니다. 이것은 소정 바운드 값 "윈도우 객체"또는 (OnDivClick가 언 바운드 함수 인 경우) 각각 비 엄격하고 엄격한 모드에서 "미등록"또는 집합으로서 설정한다 (OnDivClick 바운드 함수 인 경우)
다음은 전체 기사를 요약합니다
전역 컨텍스트에서 "this"는 항상 "window" 개체를 참조합니다.
함수가 호출될 때마다 객체( "현재 객체" ) 컨텍스트에서 호출됩니다. 현재의 객체가 명시 적으로 제공하지 않으면 현재 개체가 비 엄격 모드에서 "윈도우 객체"이고 기본적으로 엄격 모드에서 "정의되지 않은".
Non Bound 함수 내에서 "this" 의 값은 함수가 호출되는 컨텍스트에서 객체에 대한 참조입니다( "현재 객체" ).
Non Bound 함수 내에서 "this" 의 값은 함수의 호출 및 적용 메서드에 의해 재정의될 수 있습니다.
"this" 값은 Bound 함수에 대해 고정되어 있으며 함수의 호출 및 적용 메서드로 재정의할 수 없습니다.
바인딩 및 이미 바인딩된 함수는 "this" 값을 변경하지 않습니다. 첫 번째 bind 함수에서 설정한 값으로 그대로 유지됩니다.
생성자 내에서 "this" 의 값은 생성 및 초기화되는 객체입니다.
인라인 DOM 이벤트 핸들러 내의 "this" 값은 이벤트 핸들러가 제공되는 요소에 대한 참조입니다.
아마에서 가장 상세하고 포괄적 인 글 this
다음입니다 :
JavaScript의 'this' 키워드에 대한 부드러운 설명
뒤에 아이디어 this
함수 호출 유형 설정에 상당한 중요성을 가지고 이해하는 것입니다 this
값입니다.
this
식별하는 데 문제가 있는 경우 다음과 같이 자문 하지 마십시오.
this
어디 에서 가져온 것 입니까?
하지만 자신에게 물어 않습니다 :
함수는 어떻게 호출 됩니까?
화살표 기능(컨텍스트 투명도의 특별한 경우)의 경우 다음과 같이 자문해 보십시오.
화살표 함수가 정의된
this
값은 무엇입니까?
를 처리 할 때이 사고 방식은 정확 this
두통에서 당신을 저장합니다.
: 이것은 내가 본 최고의 설명이다 선명도와 자바 스크립트이 이해
이 참조는 항상 개체(단일 개체)를 참조하고 그 값을 유지하며 전역 범위의 함수 외부에서 사용할 수 있지만 일반적으로 함수 또는 메서드 내부에서 사용됩니다. 엄격 모드를 사용할 때 이것은 전역 함수와 어떤 객체에도 바인딩되지 않은 익명 함수에서 정의되지 않은 값을 유지합니다.
이것이 혼동될 수 있는 네 가지 시나리오가 있습니다.
그는 코드 예제, 설명 및 솔루션을 제공하여 매우 도움이 된다고 생각했습니다.
this
장소에 따라 약간 다르게 동작하기 때문에 JavaScript에서 잘못 이해되는 개념 중 하나입니다. 간단히 말해서, 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는 로컬에서 전역으로 범위 체인을 올라가 특정 컨텍스트 내에서 식별자를 확인합니다.
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
1 호선이 실행되면, 자바 스크립트 설정, 함수 호출의 실행 컨텍스트 (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>
자바 스크립트를 통해 이벤트 핸들러를 추가 할 때, this
이벤트가 발생 된 DOM 요소를 지칭한다.
.apply()
.call()
및 .bind()
사용하여 컨텍스트를 조작할 수도 있습니다.var that = this
는 JavaScript에서 무엇을 의미합니까?"this"의 값은 함수가 실행되는 "컨텍스트"에 따라 다릅니다. 컨텍스트는 모든 개체 또는 전역 개체(예: 창)일 수 있습니다.
따라서 "this"의 의미 체계는 전통적인 OOP 언어와 다릅니다. 그리고 다음과 같은 문제가 발생합니다. 1. 함수가 다른 변수에 전달될 때(대부분의 경우 콜백); 2. 클로저가 클래스의 멤버 메소드에서 호출될 때.
두 경우 모두 창으로 설정됩니다.
유사 고전적인 용어로, 많은 강의에서 '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;
Whould 이 도움? (자바스크립트에서 'this'에 대한 대부분의 혼동은 일반적으로 개체에 연결되어 있지 않고 현재 실행 중인 범위에 연결되어 있다는 사실에서 비롯됩니다. 정확히 작동하는 방식은 아니지만 나에게는 항상 그렇게 느껴집니다.) 완전한 설명은 기사를 참조하십시오)
이 키워드에 대한 약간의 정보
this
키워드를 전역 범위의 콘솔에 기록해 보겠습니다.
console.log(this)
클라이언트 / 브라우저에서 this
키워드는 글로벌 오브젝트입니다 window
console.log(this === window) // true
그리고
Server/Node/Javascript 런타임에서 this
module.exports
전역 개체이기도 합니다.
console.log(this === module.exports) // true console.log(this === exports) // true
exports
module.exports
대한 참조일 뿐입니다.
나는 도움이되기를 바라는 다른 답변 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);
+
및 -
및 *
와 같은 연산자가 있습니다. 라는 점 연산자도 있습니다 .
.
오른쪽의 기능으로서 유효하게 남아 수단 "패스 객체의 객체로 사용 오퍼레이터 this
함수.
예시
const bar = { name: 'bar', foo() { console.log(this); }, }; bar.foo(); // this is bar
즉, bar.foo()
const temp = bar.foo; temp.call(bar);
로 변환됩니다. 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); }
또 다른 주름은 프로토타입 체인입니다. 당신이 사용하는 경우 ab
에 의해 직접 참조 개체에 자바 스크립트에게 처음으로 모습을 속성에 대한 a
b
. b
b
를 찾기 위해 객체의 프로토타입에서 찾습니다.
객체의 프로토타입을 정의하는 방법은 다양하며 2019년에 가장 많이 사용된 것은 class
키워드입니다. this
의 목적을 위해 그것은 중요하지 않습니다. 중요한 것은 객체 a
속성 b
찾을 b
b
가 함수가 되는 경우 프로토타입 체인에서 위와 동일한 규칙이 적용된다는 것입니다. 함수 b
참조는 call
메서드를 사용하여 호출되고 이 답변의 맨 위에 표시된 것처럼 a를 objectForThis로 a
지금. 다른 함수를 호출하기 전에 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
와 마찬가지로 objectForThis
대한 바인딩된 값으로 주어진 함수를 호출하는 새로운 보이지 않는 함수가 생성 bind
와 달리 바인딩할 객체는 암시적입니다. 그것은 어떤의 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);
변환됩니다. const temp = obj.foo; temp.call(obj);
foo
내부의 화살표 연산자가 obj
b
할당된 새 보이지 않는 함수를 반환한다는 것을 의미합니다. b()
foo
만든 새로운 보이지 않는 함수를 호출하는 b.call(window)
또는 b.call(undefined)
과 같이 항상 작동합니다. 그 보이지 않는 함수는 전달된 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);
1 apply
call
과 유사한 또 다른 기능입니다.
functionName.apply(objectForThis, arrayOfArgs);
그러나 ES6부터는 개념적으로 다음과 같이 번역할 수도 있습니다.
functionName.call(objectForThis, ...arrayOfArgs);
이와 같이 범위에 대한 사용
<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
this
자바스크립트 요약:this
의 값은 함수가 생성된 위치가 아니라 호출 된 방법에 따라 결정됩니다!this
점의 왼쪽 개체에 따라 결정됩니다. (글로벌 공간의 window
this
값은 이벤트가 호출된 DOM 요소를 나타냅니다.new
this
의 값은 새로 생성된 객체를 참조합니다.call
, apply
, bind
함수를 사용하여 this
값을 조작할 수 있습니다. 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.
"이것"을 올바르게 이해하려면 문맥과 범위 및 차이점을 이해해야 합니다.
범위 : 자바스크립트에서 범위는 변수의 가시성과 관련이 있으며 범위는 함수를 사용하여 달성합니다. (범위에 대해 자세히 알아보기)
Context : Context는 객체와 관련된다. 함수가 속한 개체를 나타냅니다. JavaScript의 "this" 키워드를 사용하면 함수가 속한 객체를 가리킵니다. 예를 들어, 함수 내부에서 "this.accoutNumber"라고 말하면 해당 함수가 속한 객체에 속하는 "accoutNumber" 속성을 참조하는 것입니다.
"myObj" 객체에 "getMyName"이라는 메소드가 있는 경우 "getMyName" 내부에서 JavaScript 키워드 "this"를 사용하면 "myObj"를 참조합니다. 함수 "getMyName"이 전역 범위에서 실행된 경우 "this"는 창 개체를 나타냅니다(strict 모드 제외).
이제 몇 가지 예를 살펴보겠습니다.
<script> console.log('What is this: '+this); console.log(this); </script>
브라우저 출력에서 위의 코드를 실행하면 다음과 같습니다.
창 개체의 컨텍스트 내부에 있는 출력에 따르면 창 프로토타입이 개체를 참조하는 것도 볼 수 있습니다.
이제 함수 내부에서 시도해 보겠습니다.
<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>
이제 Scope, Self, IIFE 및 THIS가 어떻게 동작하는지 이해합시다.
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>
출처 : http:www.stackoverflow.com/questions/3127429/how-does-the-this-keyword-work
Sublime Text 2를 사용하여 HTML 코드를 어떻게 다시 포맷합니까? (0) | 2023.04.09 |
---|---|
Java에서 숫자를 소수점 이하 n자리로 반올림하는 방법 (0) | 2023.04.09 |
Android에서 중력과 layout_gravity의 차이점은 무엇입니까? (0) | 2022.07.09 |
jQuery를 사용하여 하이퍼링크의 href 속성을 변경하는 방법 (0) | 2022.07.09 |
Python의 숨겨진 기능 (0) | 2022.07.09 |