美文网首页
2.new、apply、bind、call的模拟实现

2.new、apply、bind、call的模拟实现

作者: 原来哥哥是万家灯火 | 来源:发表于2020-07-03 12:45 被阅读0次

    1.new的模拟实现

    function mockNew(constructor, argsArr) {
       var obj = {};
       obj.__proto__ = constructor.prototype;
       let result = constructor.apply(obj, argsArr);
       if (result instanceof Object) {
          return result;
       }
       return obj;
    }
    

    2.apply的模拟实现

    原理很简单,将函数赋值成context的方法,调用函数,删除方法,返回值

    Function.prototype.mockApply = function(context, argsArr) {
        var fn = this;
        var argReferenceArr = [];
    
        var globalContext = (typeof window === 'undefined')? global: window;
        context = (context instanceof Object)? context: globalContext;
    
        for (var i=0,len = argsArr.length; i<len; i++) {
            argReferenceArr.push('argsArr[' + i + ']')
        }
    
        context.f = fn;
    
        var result  = eval('context.f(' + argReferenceArr.toString() + ')');
        delete context.f;
        return result;
    }
    

    3.call的模拟实现

    Function.prototype.mockCall = function(context) {
        var fn = this;
        var argReferenceArr = [];
    
        var globalContext = (typeof window === 'undefined')? global: window;
        context = (context instanceof Object)? context: globalContext;
    
        for (var i=1,len = arguments.length; i<len; i++) {
            argReferenceArr.push('arguments[' + i + ']')
        }
    
        context.f = fn;
    
        console.log(argReferenceArr)
        var result  = eval('context.f(' + argReferenceArr.toString() + ')');
        delete context.f;
        return result;
    }
    

    4.bind的模拟实现
    bind相对复杂点,其参数可以分两次传递,如:f.bind(o, arg1)(arg2)
    另还可以当做构造函数调用,生成的实例的构造函数是f,如:

    function Human(name, age) { 
        this.name = name; 
        this.age = age; 
    }
    
    let f = Human.bind(null, '张三');
    let man = new f(20);
    console.log(man.contructor); 
    打印结果:构造函数是Human  
    

    模拟实现如下:

    Function.prototype.mockBind = function (context) {
        var fn = this;
    
        var outerArgs = [];
        var outerArgsReference = [];
    
        var globalContext = (typeof window === 'undefined') ? global : window;
        context = (context instanceof Object) ? context : globalContext;
    
        for (var i = 1, len = arguments.length; i < len; i++) {
            outerArgs[i-1] = arguments[i];
            outerArgsReference[i-1] = 'outerArgs[' + (i-1) + ']';
        }
    
    
        function bound () {
            var innerArgsReference = [];
    
            for (var i = 0, len = arguments.length; i < len; i++) {
                innerArgsReference[i] = 'arguments[' + i + ']';
            }
    
            var args = outerArgsReference.concat(innerArgsReference).toString();
            context = this instanceof fn? this: context;
            context.fn = fn;
            var result =  eval('context.fn(' + args +')');
            delete context.fn;
            return result;
        }
    
        function F() {}
        F.prototype = fn.prototype;
        bound.prototype = new F();
    
        return bound;
    }
    

    调用apply简化版:

    Function.prototype.mockBind = function (context) {
        var fn = this;
        var outerArgs = Array.prototype.slice.apply(arguments, [1]);
    
        function bound () {
            var innerArgs = [].slice.apply(arguments, [0]);
            return fn.apply(this instanceof fn? this: context, outerArgs.concat(innerArgs));
        }
    
        function F() {}
        F.prototype = fn.prototype;
        bound.prototype = new F();
    
        return bound;
    }
    

    相关文章

      网友评论

          本文标题:2.new、apply、bind、call的模拟实现

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