1、作用:
call/apply/bind的核心理念:借用方法。
借助已实现的方法,改变方法中数据的this指向,减少重复代码,节省内存。
2、区别:
call()、apply()的第一个参数相同,就是指定的对象,这个对象就是该函数的执行上下文;
不同的在于两者之间的参数:
call()在第一个参数后,后续所有参数就是传入该函数的值;
apply()只有两个参数,第一个是对象,第二个是数组,这个数组就是该函数的参数;
bind()方法的不同在于:它会返回执行上下文被改变的函数而不会立即执行,前两者
会直接执行函数。他的参数和call()相同。
fun.call(thisArg, param1, param2, ...)
fun.apply(thisArg, [param1,param2,...])
fun.bind(thisArg, param1, param2, ...)
3、使用场景
call,apply的效果完全一样,它们的区别也在于
- 参数数量/顺序确定就用call,参数数量/顺序不确定的话就用apply。
- 考虑可读性:参数数量不多就用call,参数数量比较多的话,把参数整合成数组,使用apply。
- 参数集合已经是一个数组的情况,用apply
4、手撕函数
call()
——将函数设为对象的属性
——执行并删除这个函数
——指定this到函数并传入给定参数执行函数
——如果不传入参数,默认指向window
Function.prototype.mycall = function(ctx){
ctx= ctx ? Object(ctx) : window;
ctx.fn = this;
let args = [...arguments].slice(1);
let result = ctx.fn(...args);
delete ctx.fn;
return result;
}
apply()
Function.prototype.myapply = function(ctx,arr){
ctx = ctx ? Object(ctx) : window;
ctx.fn = this;
let result;
if(!arr){
result = ctx.fn();
}else{
result = ctx.fn(...arr);
}
delete ctx.fn;
return result;
}
bind()
Function.prototype.mybind = function(ctx,...args){
const fn = this;
if(typeof this !== 'function'){
throw new TypeError('bind must be a function')
}
args = args ? args: [];
// bind会返回一个函数,不会执行,考虑new的情况
return function newFn(...newFnArgs){
if(this instanceof newFn){
return new fn(...args,...newFnArgs)
}
return fn.apply(ctx,[...args,...newFnArgs])
}
}