freeCodeCamp/guide/chinese/javascript/this-reference/index.md

176 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

---
title: this reference
localeTitle: 这个参考
---
## `this`参考
在JavaScript中每个函数都有`this`引用在声明它自动创建。该参考颇为相似, `this`在其他基于类的语言如Java或C参考JavaScript是一种基于原型的语言并没有“阶级”的概念 _它指向哪个对象有时调用的函数_ 该对象称为_上下文_ 。但是在JavaScript中 _函数内部的`this`引用可以绑定到不同的对象具体取决于调用函数的位置_ 。以下是JavaScript中`this`绑定的5个基本规则
### 规则1
在全局范围中调用函数时, `this`引用默认绑定到**全局对象** (浏览器中的`window`或Node.js中的`global` )。例如:
```javascript
function foo() {
this.a = 2;
}
foo();
console.log(a); // 2
```
注意:如果在严格模式下声明上面的`foo()`函数,那么在全局范围内调用此函数, `this`将是`undefined`并且赋值`this.a = 2`将抛出`Uncaught TypeError`异常。
### 规则2
我们来看下面的例子:
```javascript
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组件中看到的东西。
```javascript
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
```javascript
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`关键字。
```javascript
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次每半秒一次。
```javascript
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` ,或任何你想将它命名,并使用回调内部的变量。
```javascript
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`到它的限定的周围的代码的情况下。
```javascript
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();
```
### 其他资源
* [javascriptissexy.com](http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/)
* [你不懂JS](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch2.md)