本期用最简单的代码带你搞懂这个容易混淆的知识点,即 bind
、call
、apply
。
如果你想有一个深刻的印象,如下出现的每一段代码,希望你能 思考先行
,自己写下答案,再继续往下看验证自己的想法是否正确;
如果你想直接看结论,直接到文章最末尾即可。
开始吧!
1. 认识this指向
默认 this
指向全局 window
对象,而当有新的作用域产生时, this
会指向如下代码的 obj
<script type="text/javascript">
var name = '我是外部变量'
console.log('1:',this.name)
var obj = {
name: '我是内部变量',
fun: function() {
console.log('2:',this.name);
}
}
obj.fun()
</script>
答案
1:我是外部变量
2:我是内部变量
2. 认识 call、bind、apply
由第一点可知,fun
中 this
指向了 obj
,如果我们想让它指向外部变量的 name
,该怎么做呢?
注:call、bind、apply都可以用来改变 this
指向,故如下用 call
举例
<script type="text/javascript">
var name = '我是外部变量'
var obj = {
name: '我是内部变量',
fun: function() {
console.log('2:',this.name);
}
}
obj.fun.call()
</script>
答案
2: 我是外部变量
obj.fun.call( )
理解为,将 obj 下的 fun 方法中的 this,指向到外部的 window 对象去。
使得原本只能读取内部变量的方法,获得了读取外部变量的能力。
3. call、apply、bind的调用方法及参数
3.1 调用方法如下代码所示
- 第一个参数均为需要
this
指向的新对象 - 后续的参数为函数参数,不同点在于,
call
和bind
均可以接收 多个参数;而apply
只能接收 数组 call
和bind
直接执行函数,而bind
返回一个函数,需要调用才会执行,因此后面需要加一对 括号
<script type="text/javascript">
var name = '我是外部变量'
var obj = {
name: '我是内部变量',
fun: function(method) {
console.log(method+':',this.name);
}
}
var obj2 = {
name:'我是this指向的新对象'
}
obj.fun.call(obj2,'call')
obj.fun.apply(obj2,['apply'])
obj.fun.bind(obj2,'bind')()
</script>
答案
call: 我是this指向的新对象
apply: 我是this指向的新对象
bind: 我是this指向的新对象
3.2 尝试一下多参数传参
<script type="text/javascript">
var name = '我是外部变量'
var obj = {
name: '我是内部变量',
fun: function(method, age) {
console.log(method+':',this.name+';年龄为:'+age);
}
}
var obj2 = {
name:'我是this指向的新对象'
}
obj.fun.call(obj2,'call',17)
obj.fun.apply(obj2,['apply',20])
obj.fun.bind(obj2,'bind',23)()
</script>
答案
call: 我是this指向的新对象;年龄为:17
apply: 我是this指向的新对象;年龄为:20
bind: 我是this指向的新对象;年龄为:23
3.3 不传参数会怎样?
<script type="text/javascript">
var name = '我是外部变量'
var obj = {
name: '我是内部变量',
fun: function(method) {
console.log(method+':',this.name);
}
}
var obj2 = {
name:'我是this指向的新对象'
}
obj.fun.call()
obj.fun.call(null)
obj.fun.apply()
obj.fun.bind()()
</script>
答案
undefined: 我是外部变量
undefined: 我是外部变量
undefined: 我是外部变量
undefined: 我是外部变量
解析
- 第一个参数不传时(或设为
null
时),默认指向全局window
对象,因此读取到的是外部的name
变量。 - 第二个参数不传时,相当于
fun
的参数没有定义,因此method
的值为undefined
。
4. 结论
以 obj.fun.bind(this, 你)
、obj.fun.call(this, 你)
、obj.fun.apply(this, 你)
为例,作出如下结论:
- 第一个参数:均为
this
新指向的对象(比如老板(老板就是这个this)问,谁擅长编程,这时候我指了你,那么老板便会去找你交代任务(this指向你并作用于你),我在中间起的作用就是 bind、call和apply) - 第二个参数:
bind
、call
均为多参数传参,而apply
只能传数组(简记:同样四个字符的单词均为多参数传参,apply五个字符的为数组传参) - 调用后的返回值:
call
、apply
都直接返回fun
函数的执行结果,而bind
是返回一个函数,需要手动加括号进行调用,如obj.fun.bind(this, 你)()