javascript部分源码实现【持续更新】

550 阅读1分钟

本篇文章旨在总结javascript的部分方法的模拟实现,不定期积累更新,各路大神如有更加完美的实现,还望不吝赐教

1.Function.prototype.call实现

Function.prototype.myCall = function (context){
    if(!context) context = window;
    context.fn = this;
    var args = [];
    for(var i = 1;i<arguments.length;i++){
        // 避免eval解析字符串参数为变量
        args.push('arguments[' + i + ']')
    }
    var result = eval('context.fn(' + args + ')');
    delete context.fn;
    return result;
}

2.Function.prototype.apply实现

Function.prototype.myApply = function (context, args){
    if(!context) context = window;
    if(!(args instanceof Array)) args = [];
    context.fn = this;
    var newArgs = args.map(function(val, index){
        // 同上
        return 'args[' + val + ']';
    })
    var result = eval('context.fn(' + args + ')');
    delete context.fn;
    return result;
}

3.Function.prototype.bind实现

Function.prototype.myBind = function (context){
    context = context || window;
    var self = this;
    var slice = Array.prototype.slice;
    var args = slice.call(arguments, 1);

    var fbound = function(){
        var bindArgs = slice.call(arguments);
        //解决bind绑定后返回的函数当构造函数使用时候 this会失效
        self.apply(this instanceof self ? this : context, args.concat(bindArgs))
    }
    //作为构造函数使用,需继承其原型上面的方法
    fbound.prototype = Object.create(self.prototype);
    return fbound;
}

4.new操作符的实现

Reflect.construct = function(target, args){
    var obj = Object.create(target.prototype);
    var res = target.apply(obj, args);
    // 处理构造函数有返回值且返回值为对象的情况
    return typeof res === 'object' ? res : obj;
}

5.Object.is实现

修正了===对于 -0 === +0 和 NaN === NaN的误判

function is(x, y){ 
    if(x === y){ 
        return x !== 0 || y !== 0 || 1/x === 1/y 
    }else{ 
        return x !== x && y !== y 
    } 
}

6.instanceof实现

function _instanceOf(left, right){
    if(typeof left !== 'object' || left === null ) return false;
    let proto = Object.getPrototypeOf(left);
    for(;;){
        if(proto === null) return false;
        if(proto === right.prototype) return true;
        proto = Object.getPrototypeOf(proto);
    }
}

7.Object.assign实现

Object.myAssign = function(origin, ...args){
    function assignValue(left, right){
        if(typeof right !== 'object' || typeof right === null) return;
        for(let key in right){
            if(right.hasOwnProperty(key)){
                left[key] = right[key]
            }
        }
    }
    args.forEach(e => {
        assignValue(origin, e);
    })
    return origin;
}

8.async/await实现

function asyncToGenerator(generatorFun){
    return function(){
        const gen = generatorFun.apply(this, arguments);
        return new Promise((resolve, reject) => {
            function step(key, val){
                let result = null;
                try{
                    result = gen[key](val);
                }catch(err){
                    return reject(err);
                }
                const {done, value} = result;
                if(done){
                    return resolve(value);
                }else{
                    return Promise.resolve(value).then(val => {
                        step('next', val)
                    }, err => {
                        step('throw', err);
                    })
                }
            }

            step('next');
        })
    }
}
//测试
function sleep(time){
    return new Promise((resolve, reject)=>{
        setTimeout(() => {
            resolve(time)
        }, time);
    })
}

function *f(ms){
    let s1 = yield sleep(ms);
    console.log(s1)
    let s2 = yield sleep(s1);
    console.log(s2)
    let s3 = yield sleep(s2);
    return 'finish'
}

const run = asyncToGenerator(f);
run(2000).then(res => {
    console.log(res)
})