gpt4 book ai didi

javascript - “this”关键字如何工作?

转载 作者:行者123 更新时间:2023-11-28 05:07:15 24 4
gpt4 key购买 nike

我注意到,似乎没有明确解释this关键字是什么,以及如何在Stack Overflow网站上的JavaScript中正确(和不正确地)使用它。

我目睹了它的一些非常奇怪的行为,并且未能理解为什么会发生它。

this如何工作,何时应使用?

最佳答案

我建议先阅读Mike West的文章Scope in JavaScriptmirror)。这是对JavaScript中this和作用域链的概念的出色而友好的介绍。

一旦开始习惯this,规则实际上非常简单。 ECMAScript 5.1 Standard定义this


  §11.1.1 this关键字
  
  this关键字的值等于当前执行上下文的ThisBinding的值


这个绑定是JavaScript解释器在评估JavaScript代码时所维护的,例如特殊的CPU寄存器,其中包含对对象的引用。每当在以下三种情况之一中建立执行上下文时,解释器都会更新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()
将这个Binding设置为全局对象,就好像在初始全局执行上下文( §10.4.2(1))中执行一样。


§15.1.2.1.1定义了直接调用 eval()的含义。基本上, eval(...)是直接调用,而类似 (0, eval)(...)var indirectEval = eval; indirectEval(...);的东西是对 eval()的间接调用。有关何时可以使用间接 eval()调用的信息,请参见 chuckj's answer(1, eval)('this') vs eval('this') in JavaScript?Dmitry Soshnikov’s ECMA-262-5 in detail. Chapter 2. Strict Mode.

输入功能码

调用函数时会发生这种情况。如果在对象上(例如,在 obj.myMethod()或等效的 obj["myMethod"]()中)调用了函数,则ThisBinding设置为对象(示例中为 obj§13.2.1)。在大多数其他情况下,ThisBinding设置为全局对象( §10.4.3)。

之所以写“在大多数情况下”,是因为有八个ECMAScript 5内置函数可以在参数列表中指定ThisBinding。这些特殊功能采用了所谓的 thisArg,当调用函数( §10.4.3)时,它成为ThisBinding。

这些特殊的内置函数是:


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,其中,如果提供,则此绑定设置为 thisArg;否则,转到全局对象。

这些是纯JavaScript的规则。当您开始使用JavaScript库(例如jQuery)时,您可能会发现某些库函数会操纵 this的值。这些JavaScript库的开发人员这样做是因为它倾向于支持最常见的用例,并且该库的用户通常会发现此行为更加方便。将引用 this的回调函数传递给库函数时,应确保在调用该函数时有关 this的值的任何保证,请参考文档。

如果您想知道JavaScript库如何处理 this的值,则该库仅使用接受 thisArg的内置JavaScript函数之一。您也可以使用回调函数和 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);


箭头功能

Arrow functions(在ECMA6中引入)更改了 this的范围。有关更多信息,请参见现有的规范问题 Arrow function vs function declaration / expressions: Are they equivalent / exchangeable?。简而言之:


  箭头函数没有自己的 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

 这与Python不同,在Python中,访问方法( obj.myMethod)创建一个 bound method object




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

 这个很棘手。评估评估代码时, thisobj。但是,在评估代码中,未在对象上调用 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);

关于javascript - “this”关键字如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41641439/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com