美文网首页
JavaScript手写call、apply、bind方法

JavaScript手写call、apply、bind方法

作者: 六寸光阴丶 | 来源:发表于2020-04-06 19:15 被阅读0次

    写在前面

    如果本文对您有所帮助,就请点个关注吧!

    获取当前环境的公共方法

    let getEnv = function() {
      return this
    }
    

    一、手写call方法

    1. 源码

    Function.prototype.myCall = function (ctx, ...args) {
      // 设置默认的this
      ctx = arguments[0] || getEnv()
      // 若传入的对象是字符串,需要装箱
      if (ctx instanceof String) {
        ctx = new String(ctx)
      }
      // 声明一个独有的Symbol属性,防止覆盖
      const fun = Symbol('fun')
      // 为传入对象设置函数
      ctx[fun] = this
      // 执行函数并返回结果
      const result = ctx[fun](...args)
      // 删除我们设置的属性
      delete ctx[fun]
      // 返回结果
      return result
    }
    

    2. 测试

    let person = {
      name: 'person1',
      say() {
        return this.name
      }
    }
    
    let person2 = {
      name: 'person2'
    }
    
    let res = person.say.myCall(person2)
    console.log(res)
    
    // 测试结果
    // person2
    

    二、手写apply方法

    1. 源码

    Function.prototype.myApply = function (ctx, args) {
      // 设置默认的this
      ctx = arguments[0] || getEnv()
      // 若传入的对象是字符串,需要装箱
      if (ctx instanceof String) {
        ctx = new String(ctx)
      }
      // 声明一个独有的Symbol属性,防止覆盖
      const fun = Symbol('fun')
      // 为传入对象设置函数
      ctx[fun] = this
      // 执行函数并返回结果
      let result
      if (args) {
        result = ctx[fun](...args)
      } else {
        result = ctx[fun]()
      }
      // 删除我们设置的属性
      delete ctx[fun]
      // 返回结果
      return result
    }
    

    2. 测试

    let person = {
      name: 'person1',
      say(arg1, arg2) {
        return this.name + ' ' + arg1 + ' ' + arg2
      }
    }
    
    let person2 = {
      name: 'person2'
    }
    
    let res = person.say.myApply(person2, [78, 89])
    console.log(res)
    
    // 测试结果
    // person2 78 89
    

    三、手写bind方法

    1. 源码

    Function.prototype.myBind = function (ctx, ...args) {
      // 设置默认的this
      ctx = arguments[0] || getEnv()
      // 记录当前this
      const _this = this
      // 返回一个函数
      return function (...args2) {
        // 声明一个独有的Symbol属性,防止覆盖
        const fun = Symbol('fun')
        // 为传入对象设置函数
        ctx[fun] = _this
        // 执行函数并记录结果
        let result = args.length !== 0 ? ctx[fun](...args) : ctx[fun](...args2)
        // 删除我们设置的属性
        delete ctx[fun]
        // 返回调用结果
        return result
      }
    }
    

    2. 测试

    let person = {
      name: 'person1',
      say(arg1, arg2) {
        return this.name + ' ' + arg1 + ' ' + arg2
      }
    }
    
    let person2 = {
      name: 'person2'
    }
    
    let res1 = person.say.myBind(person2, 77, 78)()
    let res2 = person.say.myBind(person2)(77, 78)
    console.log(res1, res2)
    
    // 执行结果
    // person2 77 78 person2 77 78
    

    相关文章

      网友评论

          本文标题:JavaScript手写call、apply、bind方法

          本文链接:https://www.haomeiwen.com/subject/wixiphtx.html