在写js时我们会经常使用apply、call、bind快速完成一些重复性大的计算和操作。
apply函数可以传递两个参数,第一参数是改变原有函数的this指针,使其指向第一个参数,第二个参数用来传递一个数组,数组的内容是要传递的变量,可以把理解apply函数为一些语言的继承,但与继承不同,废话少说上代码:
let mydata = {
user_name: '张三',
user_age: 18
}
function UserLoad() {
this.user_name = '';
this.user_age = 0;
this.user_ico = '1.jpg';
}
UserLoad.apply(mydata);
console.log(mydata.user_ico);
console.log(mydata);
返回结果为:
此时我们可以看到mydata虽然顺利的继承到了UserLoad函数的user_ico属性,但同时我们发现原有的user_name和user_age被UserLoad的默认属性给覆盖掉,这就是与继承最大的区别.
解决方法:尽量避免接收apply指向的对象存在与函数相同的属性,若想传参可以使用apply的第二个参数进行传参
let mydata = {
user_name: '张三',
user_age: 18
}
function UserLoad(pwd, ico) {
this.user_ico = ico || '1.jpg';
this.user_pwd = pwd || '';
console.log(`用户名:${this.user_name} 密码:${this.user_pwd} 年龄:${this.user_age} 头像文件: ${this.user_ico}`);
}
UserLoad.apply(mydata, ['123456', 'ico.jpg']);
结果:
这样我们就可以实现使用apply继承部分属性并传参的操作
注意的是apply执行时会立即执行函数。
call与apply类似,只不过传参的方式由数组改为了多个变量:
let mydata = {
user_name: '张三',
user_age: 18
}
function UserLoad(pwd, ico) {
this.user_ico = ico || '1.jpg';
this.user_pwd = pwd || '';
console.log(`用户名:${this.user_name} 密码:${this.user_pwd} 年龄:${this.user_age} 头像文件: ${this.user_ico}`);
}
UserLoad.call(mydata, '123456', 'ico.jpg');
结果:
同样也是在使用call函数的时候函数体会立即执行。
bind与call和apply最大的区别在于使用bind函数进行拷贝时,函数不会执行,但会返回一个可执行的函数:
let mydata = {
user_name: '张三',
user_age: 18
}
function UserLoad(pwd, ico) {
this.user_ico = ico || '1.jpg';
this.user_pwd = pwd || '';
console.log(`用户名:${this.user_name} 密码:${this.user_pwd} 年龄:${this.user_age} 头像文件: ${this.user_ico}`);
}
let newfun = UserLoad.bind(mydata, '123456', 'ico.jpg'); //返回一个可执行函数
newfun();
newfun函数的执行结果:
总结:
通过apply和call我们可以实现对目标函数属性和方法的继承,且会立即执行函数。
通过bind可以实现对目标函数的拷贝,不会执行函数,并返回一个全新的函数对象。