三个方法的比较
相同点:
- 都是属于Function.prototype对象下的方法
- 都是为改变this指向而存在的
异同点: - 使用
call()
方法时,传递给函数的参数必须逐个列举出来, - 使用
apply()
方法时,传递给函数的是参数数组。 -
bind()
和call()
很相似,第一个参数是this的指向,从第二个参数开始是接收的参数列表。 -
bind()
方法不会立即执行,而是返回一个改变了上下文 this后的函数,用于稍后调用。 -
call()
、apply()
则是立即调用。
没有绑定this
function getProfile(name, age) {
console.log(this); // window
console.log(name, age); // tom, 18
}
getProfile("tom", 18);
绑定this
function getProfile(name, age) {
console.log(this); // {name: "kevin", age: 20}
console.log(name, age); // tom, 18
}
let obj = {
name: 'kevin',
age: 20
}
let foo = getProfile.bind(obj, 'tom', 18); // bind绑定
foo();
getProfile.call(obj, "tom", 18); // call绑定
getProfile.apply(obj, ["tom", 18]); // apply绑定
bind 实现
- 改变this指向,返回一个新函数
Function.prototype.bind = function (context) {
let self = this;
return function () {
self.apply(context, Array.prototype.slice.call(arguments, 1))
}
}
call 实现
- 改变this指向,返回函数执行结果
Function.prototype.call = function () {
let ctx = arguments[0] || window; // 保存执行上下文(绑定的this)
ctx.fn = this; // 保存执行函数
let args = [];
for (var i = 1; i < arguments.length; i++) {
args.push(`arguments[${i}]`); // 保存执行参数
}
let result = eval(`ctx.fn(${args.join(',')})`); // 获取结果
delete ctx.fn; // 删除函数
return result; // 返回结果
}
apply 实现
- 改变this指向,返回函数执行结果
Function.prototype.apply = function (ctx, arr) {
let ctx = ctx || window; // 保存执行上下文(绑定的this)
ctx.fn = this; // 保存执行函数
if (!arr) { // 没有参数
let result = ctx.fn(); // 执行函数
delete ctx.fn; // 删除函数
return result; // 返回结果
} else {
let args = [];
for (let i = 0; i < arr.length; i++) {
args.push(`arr[${i}]`); // 保存参数
}
let result = eval(`ctx.fn(${args.join(',')})`); // 执行函数
delete ctx.fn; // 删除函数
return result; // 返回结果
}
}
END
网友评论