了解'this”關鍵字的功能和適當用法
P粉155551728
P粉155551728 2023-10-12 15:50:58
0
2
596

我希望找到關於「this」關鍵字的作用以及如何正確使用它的清晰解釋。

它的行為似乎很奇怪,我不完全明白為什麼。

this如何運作以及何時應該使用它?

P粉155551728
P粉155551728

全部回覆(2)
P粉087951442

與其他語言相比,this 關鍵字在 JavaScript 中的行為有所不同。在物件導向語言中,this 關鍵字指的是該類別的目前實例。在 JavaScript 中,this 的值由函數的呼叫上下文 (context.function()#) 及其呼叫位置決定。 p>

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

即使你將 function 作為方法明確添加到物件中,它仍然遵循上述規則,即 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() + "
"); //[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() + "
"); //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() + "
"); //v1 obj2.incrementVersion(); //incrementing version in obj2 //does not affect obj1 version document.write(obj2.getVersion() + "
"); //v2 document.write(obj1.getVersion() + "
"); //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() + "
"); //[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()+"
");//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 內的值code>fun() 並呼叫fun(),傳遞argsArray 的元素作為其參數。
  • fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]]) - 設定obj1 為fun () 內部this 的值,並呼叫fun() 傳遞arg1, arg2, arg3, ... 作為其參數。
  • fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]]) - 傳回對函數的參考fun,其中fun 內的this 綁定到obj1,並且fun 的參數綁定到指定的參數arg1、arg2,arg3, ....
  • 現在,applycallbind 之間的差異一定已經很明顯了。 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)+"
"); //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]) + "
"); //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()+"
"); //15 var h = add.bind(o, 5); //h: `o.a` i.e. 4 + 5 + ? document.write(h(6) + "
"); //15 // 4 + 5 + 6 = 15 document.write(h() + "
"); //NaN //no parameter is passed to h() //thus inc2 inside add() is `undefined` //4 + 5 + undefined = NaN

7.事件處理程序內的 this

  • 當您將函數直接指派給元素的事件處理程序時,直接在事件處理函數內使用 this 來引用對應的元素。這種直接的函數分配可以使用 addeventListener 方法或透過 onclick 等傳統事件註冊方法來完成。
  • 同樣,當您直接在元素的事件屬性(如 )內使用 this 時,它指的是元素。
  • 但是,透過在事件處理函數或事件屬性內呼叫的其他函數間接使用 this 會解析為全域物件 window
  • 當我們使用 Microsoft 的事件註冊模型方法 attachEvent 將函數附加到事件處理程序時,可以實現與上述相同的行為。它不是將函數分配給事件處理程序(從而創建元素的函數方法),而是在事件上調用函數(在全局上下文中有效地調用它)。

我建議在 JSFiddle中更好地尝试此操作>.

#
sssccc

Using `this` "directly" inside event handler or event property



Using `this` "indirectly" inside event handler or event property



IE only:

8。 ES6 箭頭函數中的 this

在箭頭函數中,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 
P粉156532706

是JavaScript 中的關鍵字是執行上下文的屬性。它的主要用途是在函數和構造函數中。 this 的規則非常簡單(如果您堅持最佳實踐)。

規格中this的技術描述

ECMAScript 標準定義this 透過抽像操作(縮寫為AOResolveThisBinding

全球環境記錄模組環境記錄,以及 函數環境記錄每個都有自己的 GetThisBinding 方法。

GetThisEnvironment AO 尋找目前的執行執行上下文的LexicalEnvironment 並尋找最接近的上升環境記錄(透過迭代存取其[[OuterEnv]] 屬性),該記錄具有this 綁定(即HasThisBinding 傳回true)。此過程以三種環境記錄類型之一結束。

this 的值通常取決於程式碼是否處於 嚴格模式

GetThisBinding 的傳回值反映目前執行上下文的 this 值,因此每當建立新的執行上下文時,this 都會解析為不同的值。噹噹前執行上下文被修改時,也會發生這種情況。以下小節列出了可能發生這種情況的五種情況。

您可以將程式碼範例放入 AST 資源管理器中,以遵循規範詳細資訊。

1。腳本中的全域執行上下文

這是在頂層評估的腳本程式碼,例如直接在 内:


當在腳本的初始全域執行上下文中時,評估 this 會導致 GetThisBinding 採取以下步驟:

全域環境記錄的[[GlobalThisValue]] 屬性總是設定為主機定義的全域物件,可透過globalThis ( Web 上的window,Node.js 上的globalMDN 上的文件)。請按照 InitializeHostDefinedRealm 的步驟來了解 [[GlobalThisValue]] 屬性是如何產生的。

2。 模組

中的全域執行上下文

ECMAScript 2015 中引進了模組。

這適用於模組,例如直接位於 內部時,而不是簡單的 中。

當在模組的初始全域執行上下文中時,評估 this 會導致 GetThisBinding 採取以下步驟:

在模組中,this 的值在全域上下文中始終是未定義。模組隱式處於嚴格模式

3。輸入eval程式碼

有兩種 eval 呼叫:直接間接。這種差異自 ECMAScript 第五版以來就存在。

  • 直接eval 呼叫通常類似於eval(...);(eval)(...); (或((eval))(); 等)。 1 這只是 direct(如果呼叫表達式符合狹窄模式)。 2
  • 間接eval呼叫涉及以任何其他方式呼叫函數引用eval。它可以是eval?.(...), (..., eval)(... ), window.eval(...), eval.call(...,...)給定const aliasEval1 = eval; 等。 window.aliasEval2 = eval;,也可以是aliasEval1()aliasEval2(#)程式碼>.分別給出const originalEval = eval; window.eval = (x) => originalEval(x);,呼叫eval() 也是間接的。

請參閱 chuckj 對「(1, eval)('this') vs eval('this') in JavaScript?」的回答。 Dmitry Soshnikov 的ECMA-262- 5 詳細資訊– 第2 章:嚴格模式 (已存檔),適用於您可能使用間接 eval() 呼叫的情況。

PerformEval 執行 eval 程式碼。它創建一個新的 聲明性環境記錄 作為其 LexicalEnvironment,這是 GetThisEnvironment 從中取得 this 值。

然後,如果this出現在eval程式碼中,則GetThisEnvironment 被呼叫並傳回其值。

所建立的宣告式環境記錄取決於eval 呼叫是直接或間接的:

這意味著:

  • 在直接評估中,this 值不會改變;它取自名為 eval 的詞法作用域。
  • 在間接 eval 中,this 值是全域物件 (globalThis)。

新函數怎麼樣?  — new Functioneval類似,但它不會立即呼叫程式碼;它建立了一個函數。 this 綁定不適用於此處的任何地方,除非呼叫函數時,函數正常運作,如下一節所述。

4。輸入函數程式碼

呼叫函數時輸入函數程式碼。

呼叫函數的語法有四種類別。

#實際的函數呼叫發生在 Call AO 處,使用 thisValue 呼叫 根據上下文決定;這個參數在一長串與呼叫相關的呼叫中傳遞。 Call 呼叫 [[Call]] 函數的內部槽。這會呼叫 PrepareForOrdinaryCall,其中新的 函數環境記錄已建立:

此外,函數環境記錄中還有[[ThisValue]]欄位:

NewFunctionEnvironment 呼叫也會設定函數環境的 [[ThisBindingStatus]] 屬性。

[[Call]] 也呼叫 OrdinaryCallBindThis,其中適當的 thisArgument 基於以下因素決定:

  • 原始參考文獻,
  • 函數的類型,以及
  • 程式碼是否處於嚴格模式

確定後,最終呼叫新建立函數環境記錄的 BindThisValue 方法實際設定將 [[ThisValue]] 欄位新增至 thisArgument

最後,這個欄位就是函數環境記錄 GetThisBinding AO 從下列位置取得 this 的值:

同樣,this 值的精確確定取決於許多因素;這只是一般性概述。有了這個技術背景,我們來看看所有的具體例子。

箭頭函數

當計算箭頭函數時,[[ThisMode]]內部槽函數物件的屬性在 OrdinaryFunctionCreate 中設定為「lexical」。 p>

OrdinaryCallBindThis 處,它採用一個函數F

這僅僅意味著綁定this的演算法的其餘部分被跳過。箭頭函數不會綁定自己的 this 值。

那麼,箭頭函數中的 this 是什麼?回顧一下 ResolveThisBindingGetThisEnvironmentHasThisBinding 方法明確傳回 #。

因此,我們會迭代地尋找外部環境。這個過程將在具有 this 綁定的三個環境之一結束。

這只是意味著,在箭頭函數體中,this 來自箭頭函數的詞法範圍,或者換句話說(來自箭頭函數與函數聲明/表達式:它們是否等價/可交換?):

函數屬性

在普通函數中(function方法),this函數的呼叫方式決定。

這就是這些「語法變體」派上用場的地方。

考慮這個物件包含一個函數:

const refObj = {
    func: function(){
      console.log(this);
    }
  };

或:

const refObj = {
    func(){
      console.log(this);
    }
  };

在以下任何函數呼叫中,func 內的 this 值將為 refObj1

  • refObj.func()
  • refObj["func"]()
  • #refObj?.func()
  • #refObj.func?.()
  • #refObj.func``

#如果被呼叫的函數在語法上是基底物件的屬性,則該基底物件將是呼叫的“引用”,在通常情況下,它將是 this 的值。上面連結的評估步驟對此進行了解釋;例如,在refObj.func() (或refObj["func"]())中,# CallMemberExpression 是整個表達式refObj.func(),它由MemberExpression refObj.func參數 ()

而且,refObj.funcrefObj 扮演三個角色,分別:

  • 它們都是表達式,
  • 它們都是參考文獻,而且
  • 它們都是價值觀。

refObj.func作為是可呼叫的函數物件;對應的引用用於確定this綁定。

可選連結和標記模板範例的工作方式非常相似:基本上,引用是?.() 之前、`` 之前或()代码>。

EvaluateCall 使用 IsPropertyReference 來決定它在語法上是否是物件的屬性。它試圖取得引用的[[Base]] 屬性(例如,當應用於refObj.func 時為refObj;或foo.bar code> 當應用於foo.bar.baz 時)。如果將其寫為屬性,則 GetThisValue 將取得此 [[Base]] 屬性並使用它作為 this 值。

注意:Getters / Setters 的工作方式與方法,關於 this。簡單屬性不會影響執行上下文,例如這裡,this 在全域範圍內:

const o = {
    a: 1,
    b: this.a, // Is `globalThis.a`.
    [this.a]: 2 // Refers to `globalThis.a`.
  };

不帶基底引用、嚴格模式和 with

沒有基底引用的呼叫通常是不作為屬性呼叫的函數。例如:

func(); // As opposed to `refObj.func();`.

傳遞或指派方法,或使用逗號運算子時,也會發生這種情況。這就是參考記錄和數值之間的差異相關的地方。

注意函數j:依照規範,您會注意到j只能傳回函數物件(Value)本身,而無法傳回引用記錄。因此,基本引用 refObj 遺失。

const g = (f) => f(); // No base ref.
const h = refObj.func;
const j = () => refObj.func;

g(refObj.func);
h(); // No base ref.
j()(); // No base ref.
(0, refObj.func)(); // Another common pattern to remove the base ref.

EvaluateCall 呼叫 呼叫,此處的thisValue未定義。這在OrdinaryCallBindThis 中有所不同(F:函數物件;thisArgument:傳遞給CallthisValue) :

注意:步驟 5 將 this 的實際值設定為嚴格模式下提供的 thisArgument - 在本例中為 undefined。在「草率模式」下,未定義或 null thisArgument 會導致 this 成為全域 this 值。

如果IsPropertyReference傳回false,則EvaluateCall 採取下列步驟:

這是未定義的 thisValue 可能來自:refEnvWithBaseObject() 總是未定義除外 sec-with-statement-runtime- semantics-evaluation" rel="noreferrer">with 語句。在這種情況下,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.bindthisArg 和基底元

OrdinaryCallBindThis 的步驟5 的另一個結果,與步驟6.2(在規範),即原始this 值在「草率」模式下被強制轉換為物件。

為了檢查這一點,讓我們引入 this 值的另一個來源:重寫 this# 綁定的三個方法:4

  • #Function.prototype.apply(thisArg, argArray)
  • #Function.prototype. {呼叫, 綁定} (thisArg, ...args)李>

.bind 建立一個綁定函數,其this 綁定已設定為 thisArg 並且無法再次變更。 .call.apply 立即呼叫函數,並設定this 綁定到thisArg

.call.apply 直接對應到 Call ,使用指定的thisArg.bind 使用 BoundFunctionCreate 建立綁定函數。它們有自己的[[Call ]] 方法,它尋找函數物件的 [[BoundThis]] 內部槽。

設定自訂this值的範例:

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 運算子將函數作為建構函式呼叫時,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`.

超級 H4>

new 行為的例外是 class extends...{...},如上所述。衍生類別在呼叫時不會立即設定其this 值;它們只有在透過一系列super 呼叫到達基底類別後才會這樣做(在沒有自己的構造函數的情況下隱式發生)。不允許在呼叫 super 之前使用 this

呼叫 super 呼叫具有呼叫的詞法範圍(函數環境記錄)的 this 值的超級建構子。 GetThisValue 對於 super 呼叫有一個特殊的規則。它使用 BindThisValuethis 設定為該環境記錄。

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 }`.

5。評估類別字段

ECMAScript 2022 中引入了實例字段和靜態字段。

當評估 class 時,ClassDefinitionEvaluation 為執行,修改執行執行上下文。對於每個 ClassElement

  • 如果欄位是靜態的,則 this 指的是類別本身,
  • 如果欄位不是靜態的,則 this 引用實例。

私有欄位(例如#x)和方法被加入到私有環境中。

靜態區塊目前是TC39 第 3 階段提案。靜態區塊的工作方式與靜態欄位和方法相同:其中的 this 引用類別本身。

請注意,在方法和 getters/setters 中,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 log `demo`.
console.log(Demo.c, Demo.d()); // Both log `Demo`.

1:(o.f)() 等價於o.f(); (f)() 相當於f()這篇 2ality 文章 (已存檔)。特別請參閱如何評估ParenthesizedExpression#。

2:它必須是MemberExpression em>,不能是屬性,必須具有完全「eval」的[[ReferencedName]] ,且必須是%eval%內在物件。

3:每當規格說「讓 ref 成為評估X 的結果」時,X 是您需要找到其求值步驟的某個表達式。例如,評估 MemberExpressionCallExpression這些演算法。其中一些會產生參考記錄

4:還有其他幾種本機和主機方法允許提供this 值,特別是Array.prototype.map、Array .prototype.forEach 等接受thisArg 作為第二個參數。任何人都可以創建自己的方法來更改this,例如(func, thisArg) => func.bind(thisArg)(func, thisArg) => func 。 call(thisArg) 等。一如既往,MDN 提供了很棒的服務文件。


只是為了好玩,用一些例子來測試你的理解

對於每個程式碼片段,回答以下問題:「標記行處 this 的值是多少?為什麼?」.

要顯示答案,請點選灰色框。

  1. if(true){
      console.log(this); // What is `this` here?
    }
    

    globalThis。標記的行在初始全域執行上下文中進行計算。

  2. #
    const obj = {};
    
    function myFun(){
      return { // What is `this` here?
        "is obj": this === obj,
        "is globalThis": this === globalThis
      };
    }
    
    obj.method = myFun;
    
    console.log(obj.method());
    
       
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板