前端手写题 this指向

75 阅读2分钟

手写 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)}    //返回执行函数
}

}