“this”关键字如何运作?

问题描述 投票:1202回答:22

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

我亲眼目睹了一些非常奇怪的行为,并且无法理解为什么会发生这种行为。

this如何工作以及何时使用?

javascript this
22个回答
1272
投票

我建议先阅读Mike West的文章Scope in JavaScriptmirror)。它是对JavaScript中this和范围链概念的优秀,友好的介绍。

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

§11.1.1 The this keyword

this关键字计算为当前执行上下文的ThisBinding的值

ThisBinding是JavaScript解释器在评估JavaScript代码时维护的东西,比如一个特殊的CPU寄存器,它保存对象的引用。只要在三种不同情况之一中建立执行上下文,解释器就会更新ThisBinding:

1. Initial global execution context

这是在顶层评估的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)。

Entering eval code

  • ......通过直接调用qazxsw poi这个绑定保持不变;它与调用的executioncontext(eval()(2)(a))的ThisBinding值相同。
  • ......如果不是直接打电话给§10.4.2 ThisBinding设置为全局对象,就像在初始全局执行上下文(eval()(1))中执行一样。

§15.1.2.1.1定义了对§10.4.2的直接调用。基本上,eval()是直接调用,而像eval(...)(0, eval)(...)这样的东西是对var indirectEval = eval; indirectEval(...);的间接调用。当你可以使用间接的eval()调用时,请参阅chuckj's answer(1, eval)('this') vs eval('this') in JavaScript?Dmitry Soshnikov’s ECMA-262-5 in detail. Chapter 2. Strict Mode.

Entering function code

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

在“大多数其他情况下”编写的原因是因为有八个ECMAScript 5内置函数允许在参数列表中指定ThisBinding。这些特殊函数采用所谓的§10.4.3,在调用函数(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 ] )函数,它们在函数对象上调用,但不是将ThisBinding设置为函数对象,而是将ThisBinding设置为Function.prototype

thisArg函数的情况下,给定的Array.prototype在执行上下文中被调用,其中ThisBinding被设置为callbackfn(如果提供);否则,到全局对象。

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

如果您想知道JavaScript库如何操纵this的值,那么库只是使用一个接受this的内置JavaScript函数。您也可以使用回调函数和thisArg编写自己的函数:

thisArg

我还没有提到一个特例。通过function doWork(callbackfn, thisArg) { //... if (callbackfn != null) callbackfn.call(thisArg); } 运算符构造新对象时,JavaScript解释器创建一个新的空对象,设置一些内部属性,然后在新对象上调用构造函数。因此,当在构造函数上下文中调用函数时,new的值是解释器创建的新对象:

this

Arrow functions

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中引入)改变了Arrow functions的范围。有关更多信息,请参阅现有的规范问题this。但简而言之:

箭头函数没有自己的Arrow function vs function declaration / expressions: Are they equivalent / exchangeable? ....绑定。相反,这些标识符在词法范围内像任何其他变量一样被解析。这意味着在箭头函数内部,this ...指定箭头函数定义的环境中this的值。

只是为了好玩,用一些例子测试你的理解

要显示答案,请将鼠标悬停在浅黄色框上。

  1. this在标记线上的价值是多少?为什么? this - 标记的行在初始全局执行上下文中进行评估。 window
  2. 执行if (true) { // What is `this` here? } 时,this在标记线上的价值是多少?为什么? obj.staticFunction() - 在对象上调用函数时,ThisBinding设置为对象。 obj
  3. 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 在此示例中,JavaScript解释器输入函数代码,但由于未在对象上调用window / myFun,因此ThisBinding设置为obj.myMethod。 这与Python不同,其中访问方法(window)创建了obj.myMethodbound method object
  4. 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 这个很棘手。在评估评估代码时,windowthis。但是,在eval代码中,没有在对象上调用obj,因此对于调用,ThisBinding设置为myFunwindow
  5. function myFun() { return this; // What is `this` here? } var obj = { myMethod: function () { eval("myFun()"); } }; 在标记线上的价值是多少?为什么? thisobj正在调用特殊的内置函数myFun.call(obj);,它接受Function.prototype.call()作为第一个参数。 thisArg

9
投票

关于如何在JavaScript中解释“this”关键字存在很多困惑。希望这篇文章能够让所有人一劳永逸地休息。还有更多。请仔细阅读整篇文章。预先警告这篇文章很长。

无论使用它的上下文,“this”总是引用Javascript中的“当前对象”。但是,“当前对象”根据上下文而不同。上下文可能恰好是以下6个中的1个:

  1. 全球(即所有职能之外)
  2. 内部直接“非约束函数”调用(即未通过调用functionName.bind绑定的函数)
  3. 内部间接“非约束函数”通过functionName.call和functionName.apply调用
  4. 在“绑定函数”调用内部(即通过调用functionName.bind绑定的函数)
  5. 通过“新”创建对象
  6. 内联DOM事件处理程序

以下逐一描述每个上下文:

  1. 全球背景(即所有功能之外): 在所有函数之外(即在全局上下文中),“当前对象”(因此“this”的值)始终是浏览器的“窗口”对象。
  2. 内部直接“非约束函数”调用: 在直接“非绑定函数”调用内部,调用函数调用的对象变为“当前对象”(因此“this”的值)。如果在没有显式当前对象的情况下调用函数,则当前对象是“窗口”对象(对于非严格模式)或未定义(对于严格模式)。全局上下文中定义的任何函数(或变量)自动成为“窗口”对象的属性。例如假设函数在全局上下文中定义为 <button onclick="foo"> // In the foo - window, but you can <button onclick="foo(this)"> 它成为窗口对象的属性,就好像您已将其定义为 function UserDefinedFunction(){ alert(this) } 在“非严格模式”中,直接通过“UserDefinedFunction()”调用/调用此函数将自动调用/调用它作为“window.UserDefinedFunction()”使“窗口”成为“当前对象”(因此值“这个“)在”UserDefinedFunction“中。在”非严格模式“中调用此函数将导致以下结果 window.UserDefinedFunction=function(){ alert(this) } 在“严格模式”中,通过“UserDefinedFunction()”直接调用/调用函数将“NOT”自动调用/调用它作为“window.UserDefinedFunction()”。因此“当前对象”(以及“this”的值) )“UserDefinedFunction”中的内容应该是未定义的。在“严格模式”中调用此功能将导致以下结果 UserDefinedFunction() // displays [object Window] as it automatically gets invoked as window.UserDefinedFunction() 但是,使用window对象显式调用它将导致以下结果 UserDefinedFunction() // displays undefined 让我们看另一个例子。请查看以下代码 window.UserDefinedFunction() // "always displays [object Window] irrespective of mode." 在上面的例子中,我们看到当通过o1调用“UserDefinedFunction”时,“this”取值为o1,并显示其属性“a”和“b”的值。 “c”和“d”的值显示为未定义,因为o1未定义这些属性 类似地,当通过o2调用“UserDefinedFunction”时,“this”获取o2的值并且显示其属性“c”和“d”的值。“a”和“b”的值显示为未定义为o2没有定义这些属性。
  3. 内部间接“非约束函数”通过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 } o1.f() // Shall display 1,2,undefined,undefined o2.f() // Shall display undefined,undefined,3,4 上面的代码清楚地表明,任何“NON Bound Function”的“this”值都可以通过call / apply来改变。此外,如果未将“this”参数显式传递给call / apply,则“当前对象”(因此“this”的值)在非严格模式下设置为“window”,在严格模式下设置为“undefined”。
  4. 在“绑定函数”调用内部(即通过调用functionName.bind绑定的函数): 绑定函数是其“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 如上面的代码所示,任何“绑定函数”的“this”值都不能通过call / apply来改变。此外,如果未将“this”参数显式传递给bind,则“当前对象”(因此“this”的值)在非严格模式下设置为“window”,在严格模式下设置为“undefined”。还有一件事。绑定已绑定的函数不会更改“this”的值。它仍然设置为第一个绑定函数设置的值。
  5. 通过“新”创建对象: 在构造函数内部,“当前对象”(以及“this”的值)引用当前通过“new”创建的对象,而不管函数的绑定状态如何。但是,如果构造函数是绑定函数,则应使用为绑定函数设置的预定义参数集调用它。
  6. 内联DOM事件处理程序内部: 请查看以下HTML代码段 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”分别表示“button”元素和“div”元素。 在第一个示例中,单击按钮时的字体颜色应设置为白色。 在单击“div”元素的第二个示例中,它将调用OnDivClick函数,其第二个参数引用单击的div元素。但是,OnDivClick中“this”的值不会引用单击的div元素。它应分别在Non strict和Strict Modes中设置为“window object”或“undefined”(如果OnDivClick是未绑定的函数)或设置为预定义的Bound值(如果OnDivClick是绑定函数)

以下总结了整篇文章

  1. 在全局上下文中,“this”总是指“窗口”对象
  2. 无论何时调用函数,都会在对象(“当前对象”)的上下文中调用它。如果未显式提供当前对象,则当前对象在非严格模式下为“窗口对象”,默认情况下为严格模式下的“未定义”。
  3. 非绑定函数中“this”的值是在调用函数的上下文中对对象的引用(“当前对象”)
  4. 非绑定函数中“this”的值可以通过调用和应用函数的方法来覆盖。
  5. “this”的值对于Bound函数是固定的,并且不能通过函数的call和apply方法覆盖。
  6. 绑定和已绑定的函数不会更改“this”的值。它仍然设置为第一个绑定函数设置的值。
  7. 构造函数中“this”的值是正在创建和初始化的对象
  8. 内联DOM事件处理程序中“this”的值是对给定事件处理程序的元素的引用。

9
投票

关于<button onclick='this.style.color=white'>Hello World</button> <div style='width:100px;height:100px;' onclick='OnDivClick(event,this)'>Hello World</div> 的最详细和最全面的文章可能如下:

this

Gentle explanation of 'this' keyword in JavaScript背后的想法是要理解函数调用类型对于设置this值具有重要意义。


在识别this时遇到麻烦,不要问自己:

this从何而来?

但要问问自己:

如何调用该函数?

对于箭头函数(上下文透明度的特殊情况),请问自己:

this定义箭头函数的值是多少?

在处理this时,这种心态是正确的,并且可以避免头痛。


7
投票

这是我见过的最好的解释:this

此引用始终引用(并保持其值)对象 - 单个对象 - 它通常在函数或方法中使用,尽管它可以在全局范围内的函数外部使用。请注意,当我们使用严格模式时,它在全局函数和未绑定到任何对象的匿名函数中保存undefined的值。

有四种情况可能令人困惑:

  1. 当我们传递一个方法(使用它)作为参数用作回调函数时。
  2. 当我们使用内部函数(闭包)时。重要的是要注意闭包不能通过使用this关键字访问外部函数的this变量,因为this变量只能由函数本身访问,而不能由内部函数访问。
  3. 当依赖于此的方法被分配给跨上下文的变量时,在这种情况下,它引用另一个对象而不是最初预期的对象。
  4. 与bind,apply和call方法一起使用时。

他提供了代码示例,解释和解决方案,我认为这些非常有用。


6
投票

如果你不完全理解JS,很难掌握JS,或者写出更多的琐碎内容。你不能只是快速下降:)我认为开始使用JS的最佳方式是首先观看Douglas Crockford的这些视频讲座 - Understand JavaScripts this with Clarity,它涵盖了这个和那个,以及关于JS的所有其他内容。


6
投票

在伪古典术语中,许多讲座教授'this'关键字的方式是作为由类或对象构造函数实例化的对象。每次从一个类构造一个新对象时,想象一下,创建并返回一个'this'对象的本地实例。我记得它是这样教的:

http://yuiblog.com/crockford/

5
投票

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; 是JavaScript中被误解的概念之一,因为它在各个地方的表现差别不大。简单地说,this指的是我们当前正在执行的函数的“所有者”。

this有助于获取我们使用的当前对象(a.k.a.执行上下文)。如果你了解当前函数在哪个对象中执行,你可以很容易地理解当前的this是什么

this

上面我们创建3个同名“val”的变量。一个在全局上下文中,一个在obj中,另一个在obj的innerMethod中。 JavaScript通过从本地go全局上升范围链来解析特定上下文中的标识符。


很少有地方可以区分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

调用对象的方法

this

当执行line1时,JavaScript为函数调用建立执行上下文(EC),将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 设置为前一个“。”之前引用的对象。所以在最后一行你可以理解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 时,会创建一个全新的对象。 Person()被调用,它的Person被设置为引用该新对象。

函数调用

this

如果我们错过了qazxsw poi关键字,qazxsw poi指的是它能找到的最全球化背景(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

通过JavaScript添加事件处理程序时,window引用生成事件的DOM元素。


  • 您还可以使用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来操纵上下文
  • JQuery代理是另一种可以用来确保函数中的函数是你想要的值的方法。 (查看.apply().call()
  • .bind()

5
投票

“this”的值取决于执行函数的“上下文”。上下文可以是任何对象或全局对象,即窗口。

所以“this”的语义不同于传统的OOP语言。它会导致问题:1。当一个函数传递给另一个变量时(很可能是一个回调); 2.从类的成员方法调用闭包时。

在这两种情况下,都设置为窗口。


3
投票

Understanding $.proxy()有帮助吗? (javascript中对'this'的大多数混淆来自于它通常不与您的对象相关联,而是与当前执行范围相关联 - 这可能不是它的确切工作方式,但对我来说总是这样 - 看到文章的完整解释)


3
投票

关于这个关键字的一点信息

让我们在全局范围内将jQuery.proxy() usage关键字记录到控制台,而不需要更多代码

What does var that = this means in JavaScript

在客户端/浏览器中,this关键字是一个全局对象,它是this

console.log(this)

在Server / Node / Javascript运行时this关键字也是一个全局对象,它是window

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

请记住,this只是对module.exports的引用


1
投票

这个用于Scope就像这样

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

上面示例中的txt1和txt的值相同$(this)= $('#tbleName tbody tr')是相同的


141
投票

与其他语言相比,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关键字引用类的当前实例。在JavaScript中,this的值主要由函数的调用上下文(this)以及调用它的位置决定。

1.在全球范围内使用时

当你在全局上下文中使用context.function()时,它被绑定到全局对象(浏览器中的this

window

当你在全局上下文中定义的函数中使用document.write(this); //[object Window] 时,this仍然绑定到全局对象,因为该函数实际上是一个全局上下文的方法。

this

以上function f1() { return this; } document.write(f1()); //[object Window] 是一种全球对象的方法。因此我们也可以在f1对象上调用它,如下所示:

window

2.在对象内部使用时

在对象方法中使用function f() { return this; } document.write(window.f()); //[object Window] 关键字时,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

3.调用无上下文函数时

当您在没有任何上下文(即不在任何对象上)时调用的函数内部使用var obj1 = { name: "obj1", } function returnName() { return this + ":" + this.name; } obj1.f = returnName; //add method to object document.write(obj1.f()); //[object Object]:obj1 时,它将绑定到全局对象(浏览器中的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运算符创建其实例。
  • 同样在对象文字方法中,我们可以使用点运算符显式地将成员添加到已定义的对象。这仅添加到特定实例。但是我已经在函数原型中添加了变量,以便它反映在函数的所有实例中。

下面我尝试了上面用Object和new做的所有事情,但是先创建函数而不是直接写一个对象。

this

4.在构造函数内部使用时。

当函数用作构造函数时(即使用/********************************************************************* 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 关键字调用它时),函数体内的new指向正在构造的新对象。

this

5.在原型链中定义的函数内部使用时

如果方法在对象的原型链上,则此方法中的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 引用调用该方法的对象,就好像该方法是在对象上定义的一样。

this

6.内部调用(),apply()和bind()函数

  • 所有这些方法都在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 上定义。
  • 这些方法允许编写一次函数并在不同的上下文中调用它。换句话说,它们允许指定在执行函数时将使用的Function.prototype的值。它们还会在调用时将任何参数传递给原始函数。
  • thisfun.apply(obj1 [, argsArray])设置为obj1this的值,并将fun()fun()元素作为其参数。
  • argsArray - 将fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])设置为obj1this的值,并将fun()称为fun()作为其参数。
  • arg1, arg2, arg3, ... - 返回对函数fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])的引用,其中fun内部绑定到thisobj1的参数绑定到指定的参数fun
  • 到目前为止,arg1, arg2, arg3,...applycall之间的区别必须显而易见。 bind允许指定用作类数组对象的参数,即具有数字apply属性和相应的非负整数属性的对象。而length允许直接指定函数的参数。 callapply都会立即调用指定上下文中的函数并使用指定的参数。另一方面,call只返回绑定到指定的bind值和参数的函数。我们可以通过将其分配给变量来捕获对此返回函数的引用,之后我们可以随时调用它。
this

7. 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> 内部事件处理程序

  • 当您将函数直接赋值给元素的事件处理程序时,直接在事件处理函数内部使用this指的是相应的元素。这种直接函数赋值可以使用this方法或通过传统的事件注册方法(如addeventListener)来完成。
  • 类似地,当您在元素的事件属性(如onclick)中直接使用this时,它引用该元素。
  • 但是,通过在事件处理函数或事件属性内部调用的其他函数间接使用<button onclick="...this..." >会解析为全局对象this
  • 当我们使用Microsoft的事件注册模型方法window将函数附加到事件处理程序时,可以实现相同的上述行为。它不是将函数赋值给事件处理程序(从而构成元素的函数方法),而是调用事件上的函数(在全局上下文中有效地调用它)。

我建议在attachEvent中更好地尝试这个。

JSFiddle

8. ES6箭头功能中的<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>

在箭头函数中,this将表现为常见变量:它将从其词法范围继承。定义箭头函数的函数this将是箭头函数的this

所以,这与以下行为相同:

this

请参阅以下代码:

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

1
投票

我从其他答案中对exports有不同看法,我希望对此有所帮助。

查看JavaScript的一种方法是看到只有一种方法可以调用function1。它是

module.exports

总是为 <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> 提供一些价值。

其他一切都是this的语法糖

所以,其他一切都可以通过它如何转化为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

在JavaScript中有像'use strict'; function foo() { console.log(this); } foo(); // this is the window objectfoo(); 以及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);时,JavaScript首先查看const bar = { name: 'bar', fn1() { console.log(this); }, fn2: function() { console.log(this); }, fn3: otherFunction, }; function otherFunction() { console.log(this) }; bar.fn1(); // this is bar bar.fn2(); // this is bar bar.fn3(); // this is bar直接引用的对象{ const temp = bar.fn1; temp.call(bar); } { const temp = bar.fn2; temp.call(bar); } { const temp = bar.fn3; temp.call(bar); } 属性。如果在对象上找不到a.b,则JavaScript将查看对象的原型以查找a

有多种方法可以定义对象的原型,2019年最常见的是b关键字。出于b的目的虽然没关系。重要的是,如果它在物体b上查找属性class,如果它在对象或其原​​型链中找到属性this,如果a最终成为一个函数,那么适用于上述相同的规则。函数b引用将使用b方法调用并将b作为objectForThis传递,如此答案的顶部所示。

现在。让我们假设我们创建一个函数,在调用另一个函数之前显式设置b然后用call(点)运算符调用它

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(),但是我们明确传入了另一个objectForThis对象,所以当我们到达foo时,const temp = obj.bar; temp.call(obj);就是那个内部对象。

这就是barfoo有效的功能。它们更具语法糖。它们有效地构建了一个新的不可见函数,就像上面的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);的新的不可见函数。 foo将像objb一样工作,调用b()创建的新的隐形函数。那个看不见的函数忽略了传入它的b.call(window)并将b.call(undefined)作为objectForThis`传递给了箭头函数。

上面的代码转换为

foo

1this是另一个类似于obj的功能

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);

但从概念上讲,你可以将ES6翻译成

apply

0
投票

摘要call Javascript:

  • functionName.apply(objectForThis, arrayOfArgs); 的值取决于函数的调用方式,创建函数的位置!
  • 通常,functionName.call(objectForThis, ...arrayOfArgs); 的值由点左边的Object确定。 (this在全球空间)
  • 在事件侦听器中,this的值指的是调用事件的DOM元素。
  • 当使用this关键字调用函数时,window的值引用新创建的对象
  • 你可以使用函数来操纵this的值:newthisthis

例:

call

示例事件侦听器:

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

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

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

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

示例构造函数:

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


document.querySelector('.foo').addEventListener('click', () => {
  console.log(this);  // Tip, es6 arrow function don't have their own binding to the this v
})                    // Therefore this will log the global object

-1
投票

简单回答:

“this”关键字始终取决于调用的上下文。他们在下面提到。

  1. 功能被称为新的关键词 如果使用NEW关键字调用该函数,则THIS将绑定到新创建的对象。 .foo:hover { color: red; cursor: pointer; } 在上面这将被绑定到'myCar'对象
  2. 使用调用和应用方法显着地调用功能。 在这种情况下,THIS将绑定到显式传递给函数的对象。 <div class="foo">click me</div>
  3. 如果功能被隐瞒了对象,那么这将受到该对象的约束 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.
  4. 如果在没有任何背景的情况下被召唤,那么这将受到全球对象的约束 function Car(){ this.name="BMW"; } const myCar=new Car(); myCar.name; // output "BMW"
  5. 在严格的模式下,这将是不明确的 var obj1={"name":"bond"}; function printMessage(msg){ return msg+" "+this.name; } const message=printMessage.call(obj1,"my name is "); console.log(message); //HERE THIS WILL BE BOUND TO obj1 WHICH WE PASSED EXPLICITLY. SAME FOR APPLY METHOD ALSO.

56
投票

Javascript's 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是Web浏览器范围内的全局变量。

如果在node.js之类的环境中运行同一段代码,window将引用应用程序中的全局变量。

现在,如果我们通过在函数声明的开头添加语句this来以严格模式运行它,那么"use strict";将不再引用任何环境中的全局变量。这样做是为了避免严格模式下的混淆。 this,在这种情况下只记录this,因为它就是这样,它没有定义。

在下面的例子中,我们将看到如何操纵undefined的值。

在对象上调用函数

有不同的方法来做到这一点。如果你在Javascript中调用了本机方法,如thisforEach,你应该已经知道在这种情况下slice变量是指你调用该函数的this(请注意,在javascript中,几乎所有东西都是Object,包括Objects和Arrays)。以下面的代码为例。

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.thisMethod;
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 关键字

考虑Javascript中的构造函数:

new

这是如何运作的?好吧,让我们看看当我们使用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` 关键字时会发生什么。

  1. 使用new关键字调用函数会立即初始化new类型的Object
  2. 这个Person的构造函数的构造函数设置为Object。另外,请注意Person只返回typeof awal
  3. 这个新的Object将被分配Object的原型。这意味着Person.prototype原型中的任何方法或属性都可用于所有Person实例,包括Person
  4. 现在调用函数awal本身; Person是对新构建的对象this的引用。

很简单,嗯?

请注意,官方的ECMAScript规范没有说明这种类型的函数是实际的awal函数。它们只是普通函数,constructor可用于任何函数。只是我们这样使用它们,所以我们只将它们称为它们。

在函数上调用函数:newcall

所以是的,既然applys也是function(实际上是Javascript中的第一类变量),甚至函数都有方法......好吧,函数本身。

所有函数都继承自全局Objects,其中许多方法中的两个是Functioncall,两者都可用于在调用它们的函数中操纵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]值的相当不错的方法。

thisapply几乎相同,只接受两个参数:call和一个包含要传递给函数的参数的数组。所以上面的thisArg调用可以像这样翻译成call

apply

请注意,foo.apply(thisArg, [1,2,3]) call可以覆盖我们在第二个项目中讨论的点方法调用设置的apply的值。很简单:)

介绍.... this

bindbindcall的兄弟。它也是Javascript中全局apply构造函数的所有函数继承的方法。 Functionbind / call之间的区别在于applycall实际上都会调用该函数。另一方面,apply返回一个新函数,其中bindthisArg预设。让我们举个例子来更好地理解这个:

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的值。

另请注意,这三个函数都不会对原始函数进行任何更改。 thiscall将从新构造的函数返回值,而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。聪明,是吗?

指数:

  1. 什么是this默认举行?
  2. 如果我们将该函数称为具有Object-dot表示法的方法,该怎么办?
  3. 如果我们使用this关键字怎么办?
  4. 我们如何用newthis操纵call
  5. 使用apply
  6. 复制bind以解决嵌套范围问题。

47
投票

“这个”就是范围。每个函数都有自己的作用域,因为JS中的所有东西都是一个对象,所以即使函数也可以使用“this”将一些值存储到自身中。 OOP 101教导“this”仅适用于对象的实例。因此,每次执行一个函数时,该函数的新“实例”都具有“this”的新含义。

大多数人在尝试在匿名闭包函数中使用“this”时会感到困惑:

(function(value) {
    this.value = value;
    $('.some-elements').each(function(elt){
        elt.innerHTML = this.value;        // uh oh!! possibly undefined
    });
})(2);

所以在这里,在每个()中,“this”不包含你期望它的“值”(来自

this.value = value;
above it). So, to get over this (no pun intended) problem, a developer could:
(function(value) {
    var self = this;            // small change
    self.value = value;
    $('.some-elements').each(function(elt){
        elt.innerHTML = self.value;        // phew!! == 2 
    });
})(2);

试试看;你会开始喜欢这种编程模式


16
投票

由于这个帖子已经提升,我为this主题的新读者编写了几点。

How is the value of this determined?

我们使用类似于我们在英语等自然语言中使用代词的方式:“约翰跑得快,因为他试图赶上火车。”相反,我们可以写“......约翰试图赶上火车”。

this

在对象调用定义它的函数之前,不会为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对象的值。

windowuse strict在全局和匿名函数中没有绑定到任何对象时,其值为this

undefined关键字是this时:1)我们借用一个使用most misunderstood的方法,2)我们分配一个使用this到变量的方法,3)使用this的函数作为回调函数传递,并且4)使用this在一个闭包里面 - 一个内在的功能。 (2)

什么是未来

this中定义,箭头函数采用封闭(函数或全局)范围内的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()机制,以支持更广泛理解的词法范围。 (1)


参考文献:

  1. 这个和对象原型,由凯尔辛普森。 ©2014 Getify Solutions。
  2. javascriptissexy.com - this
  3. 安格斯·克罗尔 - http://goo.gl/pvl0GX

16
投票

JavaScript中的http://goo.gl/Z2RacU始终引用正在执行的函数的“所有者”。

如果未定义显式所有者,则引用最顶层的所有者(窗口对象)。

所以,如果我这样做

this

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

element.onclick = someKindOfFunction;将引用元素对象。但要小心,很多人犯了这个错误。

this

在后一种情况下,您只需引用该函数,而不是将其移交给元素。因此,<element onclick="someKindOfFunction()">将引用窗口对象。


12
投票

一切 功能 javascript中的执行上下文有一个 范围 上下文 此参数由以下设置:

  1. 如何调用函数(包括作为对象方法,使用call和apply,使用new)
  2. 使用bind
  3. 用于箭头函数的词法(他们采用其外部执行上下文)

无论该范围上下文是什么,都由“this”引用。

您可以 改变这一点 设置它的值 范围 上下文 使用thisfunc.callfunc.apply

默认情况下,什么混淆了大多数初学者,当a 打回来 在DOM元素上引发事件后调用listener 范围上下文 该函数的值是DOM元素。

jQuery使用jQuery.proxy改变这一点。


10
投票

func.bindHerethis的一个很好的来源。

以下是摘要:

  • 全球这个 在浏览器中,在全球范围内,JavaScriptthisobject window 在使用repl的<script type="text/javascript"> console.log(this === window); // true var foo = "bar"; console.log(this.foo); // "bar" console.log(window.foo); // "bar" 中,node是顶级命名空间。您可以将其称为thisglobal 在从脚本执行的>this { ArrayBuffer: [Function: ArrayBuffer], Int8Array: { [Function: Int8Array] BYTES_PER_ELEMENT: 1 }, Uint8Array: { [Function: Uint8Array] BYTES_PER_ELEMENT: 1 }, ... >global === this true 中,全局范围内的node作为空对象开始。它与this不同 global
  • 这个功能

除了DOM事件处理程序或提供\\test.js console.log(this); \\ {} console.log(this === global); \\ fasle 的情况(参见下文),在未使用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
  • DOM事件这个

在HTML DOM事件处理程序中,var obj = { foo: "bar", logFoo: function () { console.log(this.foo); } }; obj.logFoo(); //logs "bar" 始终是对事件附加到的DOM元素的引用

this

除非你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
  • HTML这个

在您可以放置​​JavaScript的HTML属性中,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(); 是对元素的引用。

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
  • jQuery这个

jQuery会在很多地方让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" 引用一个DOM元素。

this

9
投票

丹尼尔,很棒的解释!在事件处理程序的情况下,这个和<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)会覆盖之前和之前附加的任何其他处理程序,因此请务必小心,最好不要使用内联事件委派。感谢Zara Alaverdyan,他通过不同的辩论激励我参加这个例子清单:)

  • <element onclick="foo">
  • 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
© www.soinside.com 2019 - 2024. All rights reserved.