5.6 KiB
title, localeTitle
| title | localeTitle |
|---|---|
| this reference | 这个参考 |
this参考
在JavaScript中,每个函数都有this引用在声明它自动创建。该参考颇为相似, this在其他基于类的语言如Java或C#参考(JavaScript是一种基于原型的语言,并没有“阶级”的概念): 它指向哪个对象有时调用的函数 (该对象称为_上下文_ )。但是,在JavaScript中, 函数内部的this引用可以绑定到不同的对象,具体取决于调用函数的位置 。以下是JavaScript中this绑定的5个基本规则:
规则1
在全局范围中调用函数时, this引用默认绑定到全局对象 (浏览器中的window或Node.js中的global )。例如:
function foo() {
this.a = 2;
}
foo();
console.log(a); // 2
注意:如果在严格模式下声明上面的foo()函数,那么在全局范围内调用此函数, this将是undefined并且赋值this.a = 2将抛出Uncaught TypeError异常。
规则2
我们来看下面的例子:
function foo() {
this.a = 2;
}
var obj = {
foo: foo
};
obj.foo();
console.log(obj.a); // 2
显然,在上面的代码片段中, foo()函数被调用, _上下文_是obj对象,现在this引用绑定到obj 。因此,当使用上下文对象调用函数时, this引用将绑定到此对象。
规则3
.call , .apply和.bind都可以在调用点使用显式绑定this 。使用.bind(this)是你可以在很多React组件中看到的东西。
var foo = function() {
console.log(this.bar)
}
foo.call({ bar: 1 }) // 1
这是一个快速的例子,说明如何使用每个绑定this :
fn.call(thisObj, fnParam1, fnParam2).call():fn.call(thisObj, fnParam1, fnParam2).apply():fn.apply(thisObj, [fnParam1, fnParam2]).bind():const newFn = fn.bind(thisObj, fnParam1, fnParam2)
规则4
function Point2D(x, y) {
this.x = x;
this.y = y;
}
var p1 = new Point2D(1, 2);
console.log(p1.x); // 1
console.log(p1.y); // 2
您必须注意的是使用new关键字调用的Point2D函数,并且this引用绑定到p1对象。因此,当使用new关键字调用函数时,它将创建一个新对象,并且this引用将绑定到此对象。
注意:当您使用new关键字调用函数时,我们也将其称为_构造函数_ 。
规则5
的JavaScript确定的值this在运行时,基于所述当前上下文。所以this有时会指向你期望的东西。
考虑这个带有一个名为makeSound()的方法的Cat类示例,遵循规则4(上面)中的模式,带有构造函数和new关键字。
var Cat = function(name, sound) {
this.name = name;
this.sound = sound;
this.makeSound = function() {
console.log( this.name + ' says: ' + this.sound );
};
}
var kitty = new Cat('Fat Daddy', 'Mrrooowww');
kitty.makeSound(); // Fat Daddy says: Mrrooowww
现在让我们试着给猫一个方法来annoy()人们通过重复他的声音100次,每半秒一次。
var Cat = function(name, sound) {
this.name = name;
this.sound = sound;
this.makeSound = function() {
console.log( this.name + ' says: ' + this.sound );
};
this.annoy = function() {
var count = 0, max = 100;
var t = setInterval(function() {
this.makeSound(); // <-- this line fails with `this.makeSound is not a function`
count++;
if (count === max) {
clearTimeout(t);
}
}, 500);
};
}
var kitty = new Cat('Fat Daddy', 'Mrrooowww');
kitty.annoy();
这不起作用,因为在setInterval回调中我们创建了一个具有全局范围的新上下文,所以this不再指向我们的kitty实例。在Web浏览器中, this将指向Window对象,该对象没有makeSound()方法。
有几种方法可以使它工作:
1)创建新的上下文之前,分配this名为局部变量me ,或self ,或任何你想将它命名,并使用回调内部的变量。
var Cat = function(name, sound) {
this.name = name;
this.sound = sound;
this.makeSound = function() {
console.log( this.name + ' says: ' + this.sound );
};
this.annoy = function() {
var count = 0, max = 100;
var self = this;
var t = setInterval(function() {
self.makeSound();
count++;
if (count === max) {
clearTimeout(t);
}
}, 500);
};
}
var kitty = new Cat('Fat Daddy', 'Mrrooowww');
kitty.annoy();
2)同ES6就可以避免分配this通过使用箭头功能,其结合本地变量this到它的限定的周围的代码的情况下。
var Cat = function(name, sound) {
this.name = name;
this.sound = sound;
this.makeSound = function() {
console.log( this.name + ' says: ' + this.sound );
};
this.annoy = function() {
var count = 0, max = 100;
var t = setInterval(() => {
this.makeSound();
count++;
if (count === max) {
clearTimeout(t);
}
}, 500);
};
}
var kitty = new Cat('Fat Daddy', 'Mrrooowww');
kitty.annoy();