0%

this到底指的是谁

JavaScript中的this依赖于函数的调用方式,因此把this称为调用上下文很合适。

先来一个最简单的例子

1
2
3
4
5
6
7
8
9
10
11
function ask(){
console.log(this.name)
}
var li_lei = {
name: "han mei mei",
ask: ask
}

`这两个方法分别输出什么`
li_lei.ask() => "li lei"
han_mei_mei.ask() => "han mei mei"

稍微复杂一点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var li_lei = {
name: "li lei",
ask: function (){
console.log(this.name)
}
}

var han_mei_mei = {
name: "han_mei_mei",
ask: li_lei.ask
}

`这两个方法分别输出什么`
li_lei.ask() => "li lei"
han_mei_mei.ask() => "han mei mei"

根据上面的两个例子引出一个概念,请记住:

function中的this一般情况下表示的是调用对象(调用对象.方法名())

那么接下来需要考虑一个问题,在js里经常把function作为回调函数传来传去,用什么手段可以让function中的this保持不变?

让function中的this“保持不变”

使用bind方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var li_lei = {
name: "li lei",
_ask: function(){
console.log(this.name)
}
}
li_lei.ask = li_lei._ask.bind(li_lei)

var han_mei_mei = {
name: "han mei mei"
}
han_mei_mei.ask = li_lei.ask

`这两个方法分别输出什么`
li_lei.ask() => "li lei"
han_mei_mei.ask() => "li lei"

改成用类来举例(类的声明用es6语法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class LiLei {
constructor() {
this.name = "li lei";
this.ask = this._ask.bind(this);
}
_ask(){
console.log(this.name);
}
}

var li_lei = new LiLei();

class HanMeiMei {
constructor(li_lei_instance){
this.name = "han mei mei";
this.ask = li_lei_instance.ask
}
}

var han_mei_mei = new HanMeiMei(li_lei)

`这两个方法分别输出什么`
li_lei.ask() => "li lei"
han_mei_mei.ask() => "li lei

不使用bind实现同样的效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class LiLei {
constructor() {
this.name = "li lei";

var that = this;
this.ask = function(){
console.log(that.name);
}
}
}

var li_lei = new LiLei();

class HanMeiMei {
constructor(li_lei_instance){
this.name = "han mei mei";
this.ask = li_lei_instance.ask
}
}

var han_mei_mei = new HanMeiMei(li_lei)

`这两个方法分别输出什么`
li_lei.ask() => "li lei"
han_mei_mei.ask() => "li lei

变复杂一点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class LiLei {
constructor() {
this.name = "li lei";
this.ask = this.bind_ask();
}

bind_ask(){
var that = this;
var fun = function(){
console.log(that.name);
}
return fun;
}
}

var li_lei = new LiLei();

class HanMeiMei {
constructor(li_lei_instance){
this.name = "han mei mei";
this.ask = li_lei_instance.ask
}
}

var han_mei_mei = new HanMeiMei(li_lei)

`这两个方法分别输出什么`
li_lei.ask() => "li lei"
han_mei_mei.ask() => "li lei

使用ES6中的箭头函数来实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class LiLei {
constructor() {
this.name = "li lei";
this.ask = () => {
console.log(this.name)
};
}
}

var li_lei = new LiLei();

class HanMeiMei {
constructor(li_lei_instance){
this.name = "han mei mei";
this.ask = li_lei_instance.ask
}
}

var han_mei_mei = new HanMeiMei(li_lei)

`这两个方法分别输出什么`
li_lei.ask() => "li lei"
han_mei_mei.ask() => "li lei

ES6中的箭头函数和普通的function在处理this上是有差别的,根据上面的例子你应该已经明白了:

ES6的箭头函数中的this,永远保持不变,一只表示声明时的this