实现call、apply、bind
call的实现步骤与代码
call的实现步骤:
1、判断调用对象是否为函数
2、判断传入上下文对象是否存在,如果不存在,则设置为window
3、处理传入的参数,截取第一个参数后的所有参数
4、将函数作为上下文对象的一个属性
5、使用上下文对象来调用这个方法,并保存返回结果
6、删除刚才新增的属性
7、返回结果
call的实现代码:
Function.prototype.myCall = function(context){
//判断调用对象
if(typeof this !== "function"){
console.error("type error")
}
//获取参数
let args = [...arguments].slice(1),
result = null;
//判断context 是否传入,如果未传入则设置为window
context = context || window;
//将调用函数设置为对象的方法
context.fn = this;
//调用函数
result = context.fn(...args);
//将属性删除
delete context.fn;
return result;
};
apply的实现步骤与代码
apply的实现步骤:
1、判断调用对象是否为函数
2、判断传入上下文对象是否存在,如果不存在,则设置为window
3、将函数作为上下文对象的一个属性
4、判断参数值是否传入
5、使用上下文对象来调用这个方法,并保存返回结果
6、删除刚才新增的属性
7、返回结果
apply的实现代码:
Function.prototype.myApply = function(context){
//判断调用对象是否为函数
if(typeof this !== "function"){
throw new TypeError("Error")
}
let result = null;
//判断context 是否传入,如果未传入则设置为window
context = context || window;
//将调用函数设置为对象的方法
context.fn = this;
//调用方法
if(arguments[1]){
result = context.fn(...arguments[1])
}else{
result = context.fn();
}
//将属性删除
delete context.fn;
return result;
}
bind的实现步骤与代码
bind的实现步骤:
1、判断调用对象是否为函数
2、保存当前函数的引用,获取其余传入参数值
3、创建一个函数返回
4、函数内部使用apply来绑定函数调用,需要判断函数作为构造函数的情况,这个时候需要传入当前函数的this给apply调用,其余情况都传入指定的上下文对象
bind的实现代码:
Function.prototype.myApply = function(context){
//判断调用对象是否为函数
if(typeof this !== "function"){
throw new TypeError("Error")
}
//获取参数
var args = [...arguments].slice(1),
fn = this;
var bound = function(){
//根据调用方式,传入不同绑定值
return fn.apply(
this instanceof Fn ? this : context,
args.concat(...arguments)
);
};
f = Function(){}
f.prototype = fn.prototype
bound.prototype = new f();
return bound;
}
拓展补充:
call、apply、bind的异同点?
相同点:
三个都是用于改变this指向;
接收的第一个参数都是this要指向的对象;
都可以利用后续参数传参。
不同点:
call和bind传参相同,多个参数依次传入的;
apply只有两个参数,第二个参数为数组;
call和apply都是对函数进行直接调用,而bind方法不会立即调用函数,而是返回一个修改this后的函数。
call和apply都是临时改变this指向一次,而bind是返回一个永久改变this指向的函数。