总结
函数的 this 关键字在 JavaScript 中的行为略有不同
与其他语言相比。它之间也有一些区别
严格模式和非严格模式。
在大多数情况下,this 的值取决于函数的运行方式
叫。执行时不能通过赋值来设置,可能是
每次调用函数时都不同。 ES5 引入了绑定
设置函数 this 值的方法,无论它如何
调用。
语法 this 全局上下文 在全局执行上下文中(外部
任何函数),this指的是全局对象,无论是严格的
模式与否。
console.log(this.document === 文档); // 是的
// 在网络浏览器中,window 对象也是全局对象:
console.log(this === window); // 是的
this.a = 37;控制台.log(window.a); // 37 函数上下文
函数,this的值取决于函数的调用方式。
简单的调用
function f1(){ return this; }
f1() === window; // global object In this case, the value of this is
不是由调用设置的。由于代码不是在严格模式下,值
of this 必须始终是一个对象,因此它默认为全局对象。
function f2(){ "使用严格"; // 查看严格模式 return this; }
f2() === undefined;
在严格模式下, this 的值保持在
进入执行上下文时设置的任何值。如果不是
已定义,它仍然未定义。它也可以设置为任何值,例如
为 null 或 42 或“我不是这个”。
注意:在第二个例子中,这应该是未定义的,因为 f2 是
在不提供任何基础的情况下调用(例如 window.f2())。此功能
一些浏览器刚开始支持时没有实现
严格模式。结果,他们错误地返回了窗口对象。
作为对象方法
当一个函数作为一个对象的方法被调用时,它的 this 被设置为
调用该方法的对象。
在以下示例中,当调用 o.f() 时,在函数内部
this 绑定到 o 对象。
var o = { prop: 37, f: function() {
return this.prop; } };
console.log(o.f()); // logs 37 Note that this behavior is not at all
受函数定义方式或位置的影响。在上一个
例如,我们将函数 inline 定义为 f 成员在
o的定义。然而,我们可以很容易地定义
首先是函数,然后将其附加到 o.f.这样做会导致
相同的行为:
var o = {prop: 37};
function independent() { return this.prop; }
o.f = independent;
console.log(o.f()); // logs 37 This demonstrates that it matters only
该函数是从 o 的 f 成员调用的。
同样,this 绑定只受最直接的
会员参考。在下面的示例中,当我们调用
函数,我们称它为对象 o.b 的方法 g。这次期间
执行时,函数内部的 this 将引用 o.b.事实是
对象本身是 o 的成员,没有结果;最多
立即参考是最重要的。
o.b = {g: independent, prop: 42}; console.log(o.b.g()); // logs 42
this on the object's prototype chain
同样的概念也适用于定义在
对象的原型链。如果方法在对象的原型上
链,this 指的是调用该方法的对象,就好像
方法在对象上。
var o = {f:function(){ return this.a + this.b; }}; var p =
Object.create(o); p.a = 1; p.b = 4;
console.log(p.f()); // 5 In this example, the object assigned to the
变量 p 没有自己的 f 属性,它从它的
原型。但最终查找 f 并不重要
在 o 上找到具有该名称的成员;查找开始作为参考
p.f,所以函数内部的 this 获取对象的值
简称p。也就是说,由于 f 被称为 p 的方法,所以它的
这是指p。这是 JavaScript 的一个有趣的特性
原型继承。
这个带有getter或setter
同样,当一个函数从一个
吸气剂或二传手。用作 getter 或 setter 的函数有它的 this
绑定到设置或获取属性的对象。
function modulus(){ return Math.sqrt(this.re * this.re + this.im *
this.im); }
var o = { re: 1, im: -1, get phase(){
return Math.atan2(this.im, this.re); } };
Object.defineProperty(o, 'modulus', {
get: modulus, enumerable:true, configurable:true});
console.log(o.phase, o.modulus); // logs -0.78 1.4142 As a constructor
当一个函数用作构造函数时(使用 new 关键字),它的
this 绑定到正在构造的新对象。
注意:虽然构造函数的默认值是返回对象
被 this 引用,它可以改为返回一些其他对象(如果
返回值不是对象,则返回this对象)。
/* * 构造函数的工作方式如下: * * function MyConstructor(){ *
// 实际的函数体代码在这里。 * // 创建属性
|这个| as * // 通过分配给他们想要的。例如,* this.fum =
“名义”; * // 等等... * * // 如果函数有返回值
* // 返回一个对象的语句,该对象将是 *
// |new| 的结果表达。否则,* // 的结果
表达式是对象 * // 当前绑定到 |this| * //
(即最常见的情况)。 * } */
function C(){ this.a = 37; }
var o = new C(); console.log(o.a); // logs 37
function C2(){ this.a = 37; return {a:38}; }
o = new C2(); console.log(o.a); // logs 38 In the last example (C2),
由于在构造过程中返回了一个对象,因此新对象
这注定会被丢弃。 (这基本上使
语句“this.a = 37;”死代码。它并没有完全死去,因为
它会被执行,但可以在没有外部影响的情况下消除它。)
致电申请
如果函数在其主体中使用 this 关键字,则其值可以是
使用调用或应用绑定到调用中的特定对象
所有函数都继承自 Function.prototype 的方法。
function add(c, d){ return this.a + this.b + c + d; }
var o = {a:1, b:3};
// 第一个参数是用作 // 'this' 的对象,后续
参数在函数调用中作为 // 参数传递
add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16
// 第一个参数是用作 // 'this' 的对象,第二个
是一个数组,其 // 成员用作函数中的参数
调用 add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34 注意
调用并应用,如果作为 this 传递的值不是对象,则
将尝试使用内部将其转换为对象
ToObject 操作。因此,如果传递的值是像 7 或
'foo',它将使用相关的转换为对象
构造函数,因此原始数字 7 被转换为对象,就好像
通过 new Number(7) 和字符串 'foo' 到一个对象,就好像通过 new
字符串('foo'),例如
function bar() { console.log(Object.prototype.toString.call(this));
}
bar.call(7); // [object Number] The bind method
ECMAScript 5 引入了 Function.prototype.bind。打电话
f.bind(someObject) 创建一个具有相同主体和范围的新函数
作为 f,但在原始函数中出现这种情况时,在新函数中
函数它永久绑定到 bind 的第一个参数,
不管函数是如何使用的。
function f(){ return this.a; }
var g = f.bind({a:"azerty"}); console.log(g()); // azerty
var o = {a:37, f:f, g:g}; console.log(o.f(), o.g()); // 37, azerty As
DOM 事件处理程序
当一个函数用作事件处理程序时,它的 this 被设置为
触发事件的元素(某些浏览器不遵循此
使用其他方法动态添加的侦听器的约定
addEventListener)。
// 当作为监听器调用时,将相关元素变为蓝色函数
bluify(e){ // 始终为真 console.log(this === e.currentTarget);
// 当 currentTarget 和 target 是同一个对象时为真
console.log(this === e.target); this.style.backgroundColor =
'#A5D9F3'; }
// Get a list of every element in the document var elements =
document.getElementsByTagName('*');
// Add bluify as a click listener so when the // element is clicked
打开,它变成蓝色 for(var i=0 ; i
元素[i].addEventListener('click', blueify, false); } 在一个在线
事件处理程序
当从内联处理程序调用代码时,它的 this 被设置为
放置监听器的 DOM 元素:
显示这个
上面的警报显示按钮。但请注意,只有
外部代码是这样设置的:
显示内部
this 在这种情况下,内部函数的 this 没有设置所以它
返回全局/窗口对象(即默认对象
非严格模式,这不是由调用设置的)。