this、apply、call、bind
这是一个面试经典问题,是ES5时代的一个坑,我们利用ES6的箭头函数可以极大的避免这个this指向错误的结果
ES5中,this的指向其实可以用一句话来概括,只要牢记这句话,犯错的概率就会大大降低。
this 永远指向最后调用它的那个对象
怎么改变this的指向
改变 this 的指向一共有以下4种方法:
- 使用ES6的箭头函数
- 在函数内部定义一个that = this
- 使用apply、call、bind
- 使用new来实例化一个对象
1 | var habit = "sing"; |
上述题中很多人会想当然的觉得答案是输出”dance”,然而在不使用箭头函数的情况下,是会报错的。
因为在this.func1()中的作用域是在setTimeout中而不是在func2中,因此最后调用 setTimeout 的对象是window,window中不存在func1函数,所以报错了
1. 箭头函数
众所周知,ES6的箭头函数是可以避免ES5中使用this所遇到的指向错误的坑的。箭头函数的this始终指向上层作用域的this。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17var habit = "sing";
var xiaoming = {
habit: "dance",
func1: function() {
console.log(this.habit)
},
func2: function() {
setTimeout( ()=> {
this.func1()
},1000)
}
};
xiaoming.func2() //dance
2. 在函数内部定义一个 that = this
如果不使用箭头函数,那通常我们都会选择这种简单的方法,先在函数内部定义一个that,来把this的指向赋值给它,然后在这个函数的内部都使用这个that,这样this的指向就不会改变了。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18var habit = "sing";
var xiaoming = {
habit: "dance",
func1: function() {
console.log(this.habit)
},
func2: function() {
var that = this;
setTimeout( function() {
that.func1()
},1000)
}
};
xiaoming.func2() //dance
3. 使用apply、call、bind
使用apply、call、bind函数也是可以改变this的指向的
使用apply
1 | var habit = "sing"; |
使用call
1 | var habit = "sing"; |
使用bind
1 | var habit = "sing"; |
apply、call、bind区别
apply和call的区别:
其实apply和call的区别不大,只是参入的第二个参数类型不同。
1 | call: |
1 | apply: |
1 | bind: |
我们发现bind并没有输出,因为bind()方法是会创建一个新的函数,所以我们必须要手动去调用:1
2
3
4
5
6
7
8
9var a = {
name: "123",
fn: function (a,b) {
console.log( a + b )
}
}
var b = a.fn
b.bind(a,1,2)() //3
JS中的函数调用方式
JS中一共有4种调用方式:
- 作为一个函数调用
- 函数作为对象中的方法调用
- 使用new构造函数调用函数
- 作为函数方法调用函数(call、apply)