Javascript是一种后期绑定语言。实际上,绑定很晚。不仅this
在编译时没有绑定,甚至在运行时也没有绑定(就像大多数其他后期绑定语言一样)。在javascript中,this
是在通话期间绑定的。
绑定规则与大多数其他OO语言完全不同,这就是为什么它使许多不熟悉javascript的人感到困惑的原因。
基本上,this
在代码中使用的方式和位置不会影响this
其行为方式(无论它是独立的函数,对象字面量等都是无关紧要的),确定值的this
是如何调用函数。
规则是:
将函数称为构造函数时,将创建一个新对象并将this
其绑定到该对象。例如:
function Foo () {
this.bar = 1; // when called with the new keyword
// this refers to the object just created
}
new Foo().bar;
当被称为对象方法时,this
是指该方法所属的对象。基本上是最后一个点之前的名称。例如:
foo.bar = 1;
foo.baz = function () {
alert(this.bar); // this refers to foo when called as foo.baz()
}
foo.baz();
如果在任何函数外部使用或未将函数作为方法调用,则this
引用全局对象。javascript规范除了说全局对象不存在外,没有给全局对象起任何名字,但对于浏览器来说,传统上称为window
。例如:
bar = 1;
alert(this.bar); // this refers to the global object
foo = {
bar: this.bar // also global object
}
function foofoo () {
alert(this.bar); // also refers to the global object
}
foofoo();
在事件处理程序中(例如onclick等)this
是指触发事件的DOM元素。或者对于与DOM无关的事件,例如setTimeout
或XMLHTTPRequest
,this
指的是全局对象。例如:
foo.bar = 1;
foo.baz = function () {
alert(this.bar); // this would normally be foo but if this
// function is assigned to an event it would
// point to the element that triggered the event
}
somediv.bar = 2;
somediv.onclick = foo.baz; // clicking on somedive alerts 2 instead of 1
最后,当使用call()
或apply()
方法调用函数时,this
可以将其重新分配给任何内容(谷歌“ mdn function.prototype.call”)。这样,JavaScript中的任何对象都可以借用/窃取另一个对象的方法。例如:
cat = {
type: "cat",
explain: function () {
return "I am a " + this.type;
}
}
dog = {
type: "dog"
}
cat.explain.call(dog); // returns "I am a dog"
随着Function.bind()
现代JavaScript实现我们现在有另一个规则:
函数也可以this
使用bind()
方法显式绑定到对象。该bind
方法返回函数的新实例,该实例this
绑定到传递给的参数bind
。例如:
function explain () {
return "I am a " + this.type;
}
dog = {
type: "dog"
}
var dog_explain = explain.bind(dog);
dog_explain(); // returns "I am a dog"
ECMAscript 5引入了严格模式,该模式改变了未作为方法调用或通过call或apply调用的函数的含义,因此我们必须添加一个新规则:
在严格模式下,this
不允许引用全局对象(浏览器中的窗口)。因此,当一个函数将不会调用作为方法或this
手动通过不绑定到任何东西call
或apply
或bind
则this
变为undefined
:
"use strict";
function foo () {
return this;
}
foo(); // returns undefined instead of the global object
ECMAscript 6引入了箭头功能。箭头功能通过尽早绑定来改变行为方式。
在箭头函数中,this
在声明函数时绑定。因此this
,在以下代码中:
var x = () => {return this};
var x = function () {return this}.bind(this);
请注意,由于this
in箭头函数是在声明函数时绑定的,因此 。这是因为this
函数中的in将 指向父对象,而永远不会指向子对象。这意味着使箭头功能继承的唯一方法是覆盖父对象中的所有箭头功能。