原生js实现call&apply&bind函数

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>apply&call&bind</title>
</head>
<body>
  <script>
    /*
        func.call(thisArg,param1,param2 ...)
        func.apply(thisArg,[param1,param2, ...])
        func.bind(thisArg,param1,param2)

        参数:
        thisArg(可选)
        func的this将指向thisArg;
        非严格模式下若thisArg指定为null或者是undefined,
          则func的this指向window对象
        param(可选)
        如果不传参或是传入null或undefined,则表示不传入任何参数;
        apply的第二个参数为数组对象,传入func的参数是数组内各项的值
    */
    let obj = {
    
    
      name:'老陈',
      say:function(){
    
    
        console.log(arguments)
        console.log(this.name)
        console.log(this)
      }
    }
    let obj2 = {
    
    
      name:'老王'
    }
    // obj.say()
    // obj.say.call(obj2,1,2,3)
    // obj.say.apply(obj2,[1,2,3])
    let sayClone = obj.say.bind(obj,1,2,3)
    sayClone(4)
    // new sayClone(obj2)
    // call和apply本质上来说并没有什么区别,作用都是一致的,
    // 它们的差别体现在传入给func的参数不同,
    // call是多次传入要使用的参数,而apply传入的是一个包含要使用参数的类数组
    // call/apply和bind的区别体现在它们的返回值不同
    // call和apply的返回值是func的执行结果,在改变this指向后立即执行函数
    // 而bind的返回值是func的拷贝,在改变this指向后不会立即执行函数
    // 即需要自行调用得到的这个新函数

    // 原生javascript实现bind函数
    // ...params为es6中的解构写法
    Function.prototype.myBind = function(objThis,...params){
    
    
      const thisFn = this; // 保存当前调用的函数
      let funcForBind = function(...secondParams){
    
    
        const isNew = this instanceof funcForBind;
        const thisArg = isNew ? Object.getPrototypeOf(this) : objThis;
        return thisFn.call(thisArg,...params,...secondParams)
      }
      funcForBind.prototype = Object.create(thisFn.prototype)
      return funcForBind
    }
    let sayClone2 = obj.say.myBind(obj2,1,2,3)
    sayClone2()

    // 原生javascript实现call函数
    Function.prototype.myCall = function(thisArg,...arr){
    
    
      if(thisArg===null||thisArg===undefined){
    
    
        thisArg = window;
      }
      // 定义一个不重复的常量
      const specialMethod = Symbol('anything');
      // 将不重复的属性给到thisArg
      thisArg[specialMethod] = this
      // 调用函数并且将结果返回
      let result = thisArg[specialMethod](...arr);
      // 删除新增的属性
      delete thisArg[specialMethod]
      return result
    }
    obj.say.myCall(obj2,1,2,3)

    // 原生javascript实现apply函数
    Function.prototype.myApply = function(thisArg,arr){
    
    
      if(thisArg===null||thisArg===undefined){
    
    
        thisArg = window;
      }
      // 定义一个不重复的常量
      const specialMethod = Symbol('anything');
      // 将不重复的属性给到thisArg
      thisArg[specialMethod] = this
      // 调用函数并且将结果返回
      let result = thisArg[specialMethod](arr);
      // 删除新增的属性
      delete thisArg[specialMethod]
      return result
    }
    obj.say.myApply(obj2,1,2,3)
  </script>
</body>
</html>

Guess you like

Origin blog.csdn.net/weixin_44158539/article/details/115770459