原生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>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值