Javascript 是一种后期绑定语言。事实上,它是很晚的绑定。不仅this
在编译时不绑定,甚至在运行时也不绑定(就像大多数其他后期绑定语言一样)。在 javascript 中,this
在调用期间绑定。
绑定规则与大多数其他 OO 语言完全不同,这就是为什么它似乎让很多不熟悉 javascript 的人感到困惑。
基本上,您this
在代码中使用的方式和位置不会影响this
行为方式(无论它是独立函数、对象文字等),决定值的this
是您调用函数的方式。
规则是:
1 - 当函数作为构造函数调用时,会创建一个新对象并this
绑定到该对象。例如:
function Foo () {
this.bar = 1; // when called with the new keyword
// this refers to the object just created
}
new Foo().bar;
2 - 当作为对象调用时,方法this
是指该方法所属的对象。基本上是最后一个点之前的名称。例如:
foo.bar = 1;
foo.baz = function () {
alert(this.bar); // this refers to foo when called as foo.baz()
}
foo.baz();
3 - 如果在任何函数之外使用,或者如果函数没有作为方法调用,则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();
4 - 在事件处理程序(如 onclick 等)this
中指的是触发事件的 DOM 元素。or 对于与 DOM 不相关的事件,例如setTimeout
or 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
5 - 最后,当使用call()
orapply()
方法调用函数时,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 实现中,我们现在有另一个规则:
6 - 函数也可以使用该方法显式绑定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 引入了严格模式,它改变了函数中 this 的含义,这些函数不是作为方法调用或通过 call 或 apply 调用的,因此我们必须添加一个新规则:
7 - 在严格模式下,this
不允许引用全局对象(浏览器中的窗口)。因此,当一个函数没有作为方法调用或没有通过orthis
手动绑定到任何东西时,然后变为:call
apply
bind
this
undefined
"use strict";
function foo () {
return this;
}
foo(); // returns undefined instead of the global object
ECMAscript 6 引入了箭头函数。箭头函数通过提前绑定来改变 this 的行为方式。
8 - 在箭头函数中,this
在函数声明时绑定。所以this
在下面的代码中:
var x = () => {return this};
就好像函数被声明为如下代码:
var x = function () {return this}.bind(this);
Note that since the this
in arrow functions are bound at the time the function is declared you can't use arrow functions if you want to use inheritance. That's because the this
in the function will always point to the parent object and will never point to the child object. That means that the only way to make inheritance work with arrow function is to override all arrow functions from the parent object.