美文网首页
自定义javascript中call、bind、apply方法

自定义javascript中call、bind、apply方法

作者: 一颗冰淇淋 | 来源:发表于2021-10-31 21:06 被阅读0次

    call、bind、apply都是Function原型上的方法,用于改变this的指向

    自定义函数

    js中的call、bind、apply是用c++代码实现的,我们这里使用js代码做一个模式,没有把所有的边界情况考虑进来,仅做一个简单的实现,三个函数在使用的时候有一些需要注意的地方,在定义的时候需要把这些情况考虑进去

    • 当传入的值是基本数据类型时,call、apply、bind方法会将它转变成引用数据类型,如传入的字符串变成了 String 类型,通过Object()可以做这一转换
    • 当没有传递需要改变的this指向时,函数的this指向window(非严格模式下)
    • 当传递的this指向为null、undefined时, 函数的this指向window(非严格模式下)

    call的实现

    定义call函数需要注意

    • 第一个参数接收改变后的this指向,从第二个参数开始接收函数执行所需要的参数

    实现代码如下

    Function.prototype.iCall = function (thisArg, ...args) {
      // 1.获取执行函数
      var fn = this
      
      // 2.将函数绑定到传递的对象上
      thisArg = thisArg || thisArg.toString() ? Object(thisArg) : window
      thisArg.fn = fn
      var result = thisArg.fn(...args)
      
      // 3.删除传递对象的fn函数
      delete thisArg.fn
      
      // 4.返回结果
      return result
    }
    
    function foo(...args) {
      console.log('绑定的this为:', this)
      console.log('传递的参数为:', args)
    }
    
    var user = {
      name: 'alice'
    }
    
    // 将foo函数this指向改为user,并传递参数1,2,3
    foo.iCall(user, 1, 2, 3)
    

    执行结果为

    绑定的this为:{name: 'alice', fn: f}
    传递的参数为:[1, 2, 3]
    

    apply的实现

    定义apply函数需注意

    • 第一个参数接收改变后的this指向,第二个参数接收函数执行所需要的参数组成的【数组】

    实现代码如下

    Function.prototype.iApply = function(thisArg, args){
       // 1.获取执行函数
       var fn = this
       // 2.将函数绑定到传递的对象上
       thisArg = thisArg || thisArg.toString() ? Object(thisArg) : window
       thisArg.fn = fn
       var result = thisArg.fn(...args)
     
       // 3.删除传递对象的fn函数
       delete thisArg.fn
     
       // 4.返回结果
       return result
    }
    
    function foo(...args){
      console.log('绑定的this为:', this)
      console.log('传递的参数为:', args)
    }
    
    var str = "hello js"
    var arr = ['a', 'b', 'c']
    
    foo.iApply(str, arr)
    

    执行结果如下

    绑定的this为:{'hello js', fn: f}
    传递的参数为:['a', 'b', 'c']
    

    bind的实现

    定义bind函数需注意

    • 第一个参数接收改变后的this指向,第二个参数接收函数执行所需要的参数
    • bind函数不会立即调用函数,而是返回一个新的函数,新函数仍然可以继续传递参数
    Function.prototype.iBind = function (thisArg, ...args) {
      // 1.获取执行函数
      var fn = this
      
      // 2.将函数绑定到传递的对象上
      thisArg = thisArg || thisArg.toString() ? Object(thisArg) : window
      thisArg.fn = fn
      
      return function (...params) {
        // 3.获取函数执行的结果
        var result = thisArg.fn(...args, ...params)
        
        // 4.删除传递对象的fn函数
        delete thisArg.fn
        
        // 5.返回结果
        return result
      }
    }
    
    function foo(...args) {
      console.log('绑定的this为:', this)
      console.log('传递的参数为:', args)
    }
    var num = 0
    
    var fn = foo.iBind(num, 20, 40)
    fn(30, 50)
    

    执行结果如下

    绑定的this为:{0, fn: f}
    传递的参数为:[20, 40, 30, 50]
    

    以上就是call、bind、apply的实现方法,代码量不多,但是需要对this的指向比较了解,关于this指向也可以看看我其他的博文~

    相关文章

      网友评论

          本文标题:自定义javascript中call、bind、apply方法

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