zoukankan      html  css  js  c++  java
  • 记录call、apply、bind的源码

    记录一下call、apply、bind的源码,然后从根本上明白其用法。

    都知道call、apply与bind的用法,call(this,...arguments)、apply(this,[arguments])、var fn = bind(this, ...arguments);fn(...newarguments);

    call和apply都是立即执行,只是传参数形式不一样,call参数一字排开,apply参数是数组,bind绑定之后返回一个新函数但是并不立即执行,需要额外调用的时候才执行,并且,绑定的时候可以额外传参数,执行的时候也可以额外传参数。

    call和apply执行的本质是,往要绑定的context对象下添加该函数,然后执行,最后将属性删除。当context值为null,或者undefined时,非严格模式下,它将替换为window或者global全局变量。

    Function.prototype.call = function (context) {
        var context = context || window;
        context.fn = this;
    
        var args = [];
        for(var i = 1, len = arguments.length; i < len; i++) {
            args.push('arguments[' + i + ']');
        }
    
        var result = eval('context.fn(' + args +')');
    
        delete context.fn
        return result;
    }
    Function.prototype.apply = function (context, arr) {
        var context = Object(context) || window;
        context.fn = this;
    
        var result;
        if (!arr) {
            result = context.fn();
        }
        else {
            var args = [];
            for (var i = 0, len = arr.length; i < len; i++) {
                args.push('arr[' + i + ']');
            }
            result = eval('context.fn(' + args + ')')
        }
    
        delete context.fn
        return result;
    }

    bind因为不会立刻执行,而是返回一个函数,一般情况下,该函数执行时的this指向绑定的对象。而麻烦的是JS中该函数还可以通过new来实例化,而实例化之后的this要指向新创建的对象,不能再跟着绑定的对象走了,所以该函数内部对this进行了额外处理,看它是否是通过new创建的实例,如果是通过new创建的实例,this对象指向新创建的new对象实例。

    if (!Function.prototype.bind) {
      Function.prototype.bind = function (oThis) {
        if (typeof this !== "function") {
          throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
        }
    
        var aArgs = Array.prototype.slice.call(arguments, 1), // 绑定函数时,传入的参数
            fToBind = this, // 要绑定的函数
            fNOP = function () {},
            fBound = function () { // 绑定后的函数实际调用时,执行的是它,
              return fToBind.apply(this instanceof fNOP
                                     ? this // 如果调用时使用的是new调用,它的绑定对象就是this了
                                     : oThis || this, // 如果是正常调用,它的绑定对象就是第一次bind的时候的oThis
                                   aArgs.concat(Array.prototype.slice.call(arguments))); // 将绑定时传入的参数与调用时传入的参数合并处理
            };
      // 这两步为了确定,返回的fBound执行时是否用new调用的
        fNOP.prototype = this.prototype;
        fBound.prototype = new fNOP();
    
        return fBound; // 返回的函数
      };
    }
  • 相关阅读:
    EZOJ #202
    EZOJ #201
    p5156 [USACO18DEC]Sort It Out
    p4363 [九省联考2018]一双木棋chess
    p2150 [NOI2015]寿司晚宴
    p5155 [USACO18DEC]Balance Beam
    p2414 [NOI2011]阿狸的打字机
    实验室断网的解决方案
    人需要看到未来
    门德尔松--罗辑思维
  • 原文地址:https://www.cnblogs.com/liujiekun/p/11295183.html
Copyright © 2011-2022 走看看