美文网首页
手写 call

手写 call

作者: 弹指一挥间_e5a3 | 来源:发表于2020-03-13 18:18 被阅读0次

    call 的功能

    var obj = {
        value:1
    }
    function foo(){
        console.log(this.value)
    }
    foo.call(obj)  //1
    

    上段代码可以看出 call的功能:

    • 改变了 foo 函数 this 的指向. 默认foothis 应该是 window . call 之后变为了 对象 ob 了.
    • 并且 foo 函数还执行了.

    基于此,我们可以这么写:

    第一版:

    Function.prototype.call2 = function(context){
          context.fn = this;
          context.fn();
          delete context.fn;
    }
    foo.call2(obj); // 1
    

    上面代码中的 this 就是被执行的函数 foo(); context 就是传入的对象 obj. 不信你可以自行打印一下.

    等同于, 这里需要细品:

    var obj = {
        value:1,
        foo:function(){
            console.log(this.value)
      }
    }
    obj.foo() //1
    

    第二版

    第二版解决的问题是 call 能够传入参数的问题,而上一版写的没有这个功能.
    例如:

    var obj = {
      value:1
    }
    function foo(name,age){
      console.log(name)
      console.log(age)
      console.log(this.value)
    }
    foo.call(obj,'wuxuwei',18)  // 1 'wuxuwei' 18
    

    这个其实简单,因为函数有个 arguments . 写法如下

    Function.prototype.call2 = function(context){
      context.fn = this;
      const args = [];
      for(let i = 1, len = arguments.length; i < len ; i++){
        args.push(arguments[i]);
      };
      context.fn(...args);
      delete context.fn
    }
    foo.call2(obj,'wuxuwei',18)  // 1 'wuxuwei' 18
    

    第三版(终极版)

    这一版需要解决两个问题

    1.this 参数可以传 null,当为 null 的时候,视为指向 window

    var value = 2;
    
    function bar() {
        console.log(this.value);
    }
    
    bar.call(null); // 2
    
    2.函数是可以有返回值的!
    var obj = {
        value: 1
    }
    
    function foo(name, age) {
        return {
            value: this.value,
            name: name,
            age: age
        }
    }
    
    console.log(foo.call(obj, 'wuxuwei', 18));
    // Object {
    //    value: 1,
    //    name: 'wuxuwei',
    //    age: 18
    // }
    

    基于此,我们这么写:

      var context = context || window;
      context.fn = this;
      console.log(context);
      const args = [];
      for(var i = 1, len = arguments.length; i < len; i++) {
            args.push( arguments[i]);
      }
      var result = context.fn(...args);
      delete context.fn
      return result
    foo.call2(null)
    console.log(foo.call2(obj,'wuxuwei',18))
    // 2
    // Object {
    //    value: 1,
    //    name: 'kevin',
    //    age: 18
    // }
    

    相关文章

      网友评论

          本文标题:手写 call

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