首先这三个方法的用法比较相似,但是作用,bind和前两者则完全不同。
call和apply是调用函数,bind却是返回一个新的函数。
下面看一下MDN对三者的解释:
call() 方法调用一个函数, 其具有一个指定的this值和分别地提供的参数(参数的列表)。
apply() 方法调用一个函数, 其具有一个指定的this值,以及作为一个数组(或类似数组的对象)提供的参数。
bind()方法创建一个新的函数, 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。
官方文档翻译的实在是语句不通啊,只能臆测加实现了。
总结一下共同点:
1、都是函数的方法。
2、都会通过传递第一个参数改变函数调用的this
3、都可以向函数传递参数。
那不同点呢,首先说一下call和apply的不同点。
call和apply的不同点只有一点,那就是向函数传递参数的方式不同。call是逐个的向函数传递参数,apply是通过将参数以数组的形式传递到函数中。代码如下:
// 通常状况下Max.max的参数是逐个分开的,如 Math.max(1,2,3,4,5,6,7)
// 但是现在有一个数组需要用Math.max获取最大值该如何做呢?
// Math.max([1,2,3,4,5,6,7])这样肯定是不行的。这就用到了apply
let max = Math.max(1,2,3,4,5,6,7)
let maxApply = Math.max.apply(null,[1,2,3,4,5,6,7])
console.log(maxApply)
以上便是call和apply的不同了,除了这点不同其他就都相同了。
那call和apply如何改变函数的this呢,看代码:
var tim = {
name: 'tim',
age: 20,
getName: function() {
console.log(this.name);
return this.name;
}
}
var jake = { name: 'jake', age: 20 }
tim.getName(); // tim
// jake对象没有getName方法,但是可以通过call/apply去使用tim对象的getName方法
tim.getName.call(jake); // jake
tim.getName.apply(jake); // jake
大家需要注意的是,call和apply在改变函数this的同时,执行了函数,这点和bind是不同的,后面会说。
下面总结了call和apply的一些常用的地方。
1、将类数组形式转换为数组
// arguments
// 返回值为数组,arguments保持不变
var arg = [].slice.call(arguments);
// nodeList
var nList = [].slice.call(document.getElementsByTagName('li'));
2、方法借用,改变函数的this
var foo = {
name: 'joker',
showName: function() {
console.log(this.name);
}
};
var bar = {
name: 'rose'
};
foo.showName.call(bar); // rose
3、在继承中应用
// parent
var Person = function(name) {
this.name = name;
this.gender = ['man', 'woman'];
}
// child
var Student = function(name, age) {
// inherit
Person.call(this);
}
Student.prototype.message = function() {
console.log('name:'+this.name+', age:'+this.age+', gender:.'+this.gender[0]);
}
var xm = new Student('xiaom', 12);
xm.message(); //name:undefined, age:undefined, gender:.man
4、判断数据的类型
let arrayType = Object.prototype.toString.apply([])
let objType = Object.prototype.toString.apply({})
let stringType = Object.prototype.toString.apply("wwwww")
let numberType = Object.prototype.toString.apply(1111)
let nullType = Object.prototype.toString.apply(null)
let undefinedType = Object.prototype.toString.apply(c)
console.log(arrayType,objType,stringType,numberType,nullType,undefinedType)
上面的apply换成call也可以,打印结果如图:
call和apply的相同点和不同点说完了,下面看一看bind的用法,前面一直重申函数调用bind后返回一个新的函数。并不像call和apply,直接调用函数。执行如下代码:
function sum(a,b){
console.log(a,b)
}
sum.call(null,1,2);
sum.apply(null,[1,2])
sum.bind(null,1,2)
打印结果如下:
只打印了两次,为什么sum.bind(null,1,2)没有执行呢?咱们将代码修改一下:
function sum(a,b){
console.log(a,b)
}
sum.call(null,1,2);
sum.apply(null,[1,2])
let fn = sum.bind(null,1,2)
fn()
打印结果如下:
函数调用bind方法之后返回了一个函数,这个函数必须手动调用一下。
有得时候我们只想改变函数的this值并不想当时就调用,bind方法会更合适。还有就是bind向函数传递参数也是逐个传递的,这点类似call。
以上便是call apply bind的具体用法了,你有没有比着代码敲一下呢?赶紧打开电脑测试验证一下吧。