手写 call
call 执行当前函数,并改变当前函数的this指向 为 我们想要的对象
slice() 方法会返回一个新数组,该数组包含从原数组中提取的元素。不会改变原数组
arr.slice([begin[, end]])
begin(可选):代表提取起始位置的索引。若省略该参数,默认从索引 0 开始。要是该参数为负数,就表示从数组末尾开始计数,-1表示最后一个元素。end(可选):表示提取结束位置的索引,但不包含该索引对应的元素。若省略该参数,默认提取到数组末尾。若此参数为负数,同样表示从数组末尾开始计数。- 当不传入任何参数时,
slice()方法会返回原数组的一个浅拷贝 - 指定
begin为 2,意味着从索引 2 开始提取元素,直至数组末尾。 - 指定
begin为 1,end为 3,那么会从索引 1 开始提取元素,到索引 3 结束(不包含索引 3 对应的元素)。 - 使用负索引
-3表示从倒数第 3 个元素开始,-1表示到倒数第 1 个元素结束(不包含该元素)。
Function.prototype.mycall=function(context){ //context 要改变的this指向
let args=[...arguments].slice(1) //拿到传入的参数 sub.newCall(add,1,2)
context=context||window
context.fn=this
let res=context.fn(...args)
return res
}
手写 apply 调用函数,传入的参数必须是数组
Function.prototype.myapply=function(context){
context=context||window
context.fn=this //改变this指向 this指向调用函数
let res=null //函数调用的返回值
//如果在调用函数时,传入参数;执行函数
if(arguments[1]) { res=context.fn(...arguments[1] return res }
else { res=context.fn() return res }
return res
}
手写 bind 只改变this指向,不调用函数
特殊的地点在于,如果是使用了new方式 调用一个新函数。
因为 new 操作符会创建一个新对象,并且这个新对象会成为函数执行时的 this,而不是 bind 时指定的上下文。
Function.prototype.mybind=function(context){
let args=[...arguments].slice(1) //拿到第一个剩余参数
var fn=this //拿到原始函数
return function Fn(){ //返回一个新函数
args2=Array.prototype.slice.call(arguments) //第二个参数
let argsall=args.concat(args2)
if( Object.getPrototypeOf(this===Fn.prototype() ){ //判断是不是new的
return new fn(...argsall)
}
return fn.apply(...argsall)} //返回执行函数
}
}