call、apply和bind
看一段代码先
function add(a, b) {
return a + b
}
add(1, 2) // 3
上面的add(1, 2)就是调用(或者执行)add函数,这是JavaScript里面最为常见的调用函数的方式。
call、apply和bind,他们也都是调用函数的方式
使用call调用函数
上面的add(1, 2),括号里面的1和2是穿进去的参数,是实参,在使用call调用函数时,参数的第一个需要插入一个 "东西",这个"东西"是一个对象,后面的参数接着往后挤一下,看一下使用的方式:
var o = {
a:1
}
a = 2
function test() {
console.log(this.a)
}
test() // 2
这里的this指向window,而 a = 2
是window上的变量,所以输出2
再换一段代码
var o = {
a:1
}
a = 2
function test() {
console.log(this.a)
}
test.call(o) //1
这里会输出1
因为使用 call 执行函数的时候,call 的第一个参数会变成函数里面的this
this是一个会变的东西,大多数情况下都需要根据不同的环境来推测this是什么对象
而且,在古老的汇编语言中,就是使用call 来调用函数的
因此,在有this存在的函数中,可以使用call 来调用函数,强制指定this
使用apply调用函数
apply的使用方式和call类似,都会指定函数内部的this,区别是:当参数过多或者参数不明确时,需要使用apply
代码
function log(){
return console.log.apply(console, arguments)
}
这个函数定义了一个自己的log函数,console 也是一个对象,log是console对象内的一个方法,arguments是实参列表(传进来的参数形成的类数组)
这样,在使用log函数的时候可以少写几个字,当代码中的log函数过多时,并且上线的代码不能有log,可以把上面的log函数改成这样
function log(){}
把log函数变成一个空的,下面代码中所有的log函数也就失效了
bind
看一段代码:
var log = console.log.bind(console)
这段代码和上面定义的log函数是一样的功能,这里的log也是一个函数,并不是一个对象,因为bind写在函数体后的时候,会形成一个新的函数,定义的log就是就收这个新函数的
bind还有另外一个功能,和前面一样,第一个参数会改变函数内this的指向
var d = document.querySelector('div')
var o = {
a: 2,
click:function(){
d.onclick = function(){
console.log(this.a)
this.a ++
}
}
}
o.click()
这段代码的目的是想使div在点击的时候,让 o 对象内的a ++,但是实际上却做不到,因为onclick函数内的this会指向被绑定事件的节点对象,也就是这个div,想让this 变成 o 对象,可以使用bind 方法
var d = document.querySelector('div')
var o = {
a: 2,
click:function(){
d.onclick = function(){
console.log(this.a)
this.a ++
}.bind(this)
}
}
o.click()
这样,onclick 函数内部的this ,就是全是外部 提供的