三道原生js面试题(面向高级)

这三题原本是公司为招聘的前端开发工程师定职级准备的题目,分别考察了库里化、中间件、回调函数的应用。独乐乐不如众乐乐,分享给大家,共同提升对原生js的理解~

话不多说,亮题~

大家如果有更好的实现方法欢迎提出探讨~


1.编写curry.js

实现函数的分步调用

var curry = require('./curry.js');// <- this is the file you make;

function add(a, b) {
    return a + b;
}

var curried = curry(add);
console.log(curried(1)(2));

function add2(a, b, c) {
    return a + b + c;
}

var curried2 = curry(add2);
console.log(curried2(1)(2)(3));

function add3(a, b, c, d) {
    return a + b + c + d;
}

var curried3 = curry(add3);
console.log(curried3(1)(2)(3)(4));

2.编写middleware.js

实现中间件类,可以使用use添加中间件,go执行

var Middleware = require('./middleware.js');  // <- this is the file you make;

var middleware = new Middleware();

middleware.use(function(next) {
    var self = this;
    setTimeout(function() {
        self.hook1 = true;
        next();
    }, 10);
});

middleware.use(function(next) {
    var self = this;
    setTimeout(function() {
        self.hook2 = true;
        next();
    }, 10);
});

var start = new Date();
middleware.go(function() {
    console.log(this.hook1); 
    // true
    console.log(this.hook2); 
    // true
    console.log(new Date() - start); 
    // around 20
});

3.编写async.js

实现一个async对象,为此对象封装了方法,可以进行事件的队列、并行、竞速的处理。

var async = require('./async.js');// <- this is the file you make;

var getUser = function(userId) {
    return function(cb) {
        setTimeout(function() {
            cb(null, {userId: userId, name: 'Joe'});
        },  100);
    };
};

var upperCaseName = function(cb, user) {
    cb(null, user.name.toUpperCase());
};

var lowerCaseName = function(cb, name) {
    cb(null, name.toLowerCase())
}

var userThunk = getUser(22);

async.sequence([userThunk, upperCaseName,lowerCaseName])(function(err, data) {
    console.log(data); 
});


var userThunk1 = getUser(1);
var userThunk2 = getUser(2);

async.parallel([userThunk1, userThunk2])(function(err, users) {
    console.log(users); 
    // [ { userId: 1, name: 'Joe' }, { userId: 2, name: 'Joe' } ]
});

var faster = function(cb) {
    setTimeout(cb.bind(null, null, "I'm faster"), 10);
};

async.race([userThunk1, faster])(function(err, winner) {
    console.log(winner); 
    // I'm faster
});

答案分割线(相信大家都会自觉噢O(∩_∩)O)


(答案不唯一):

1.curry.js

function curry (fn){
    var args = [].slice.call(arguments, 1)
    return function () {
        const newArgs = args.concat(Array.from(arguments))
        if (newArgs.length < fn.length) {
            return curry(fn, ...newArgs)
        } else{
            return fn(...newArgs)
        }
    }
}
module.exports = curry;

2.middleware.js

/**
 * 构造函数 
 * 函数为参数,函数内部this共享
 * use,go方法定下中间件队列,同步执行
 * 调用next可以进入下一步,如果没有调用就会停止
 */
class MiddleWare {
    constructor() {
        this.queue = []
    }
    use(fn) {
        this.queue.push(fn)
        return this
    }
    go(fn) {
        this.queue.push(fn)
        this.next()
    }
    next() {
        if( this.queue.length > 0  ){
            var fn = this.queue.shift()
            fn.call(this, this.next.bind(this))
        }
    }
}


 module.exports = MiddleWare

3.async.js

/**
 * 实现async对象,对promise进行封装
 * 函数1:队列模式,有先后关系
 *  前一个事件函数中执行cb第一个参数为报错, 第二个参数为结果
 *  最后后一个时间函数接受参数,第一个为cb,第二个参数为前一次的结果    前一个函数调用后面的callback
 * 函数2:并行模式,同时执行
 * 函数3:竞速模式,执行先到达的那个
 */

 const async = {
    sequence(events) {
        var length = events.length;
        var i = 0;
        return function(cb) {
            var middleFn = function(error, data){
                if( !error ) {
                    if( i + 2 >= length ) {
                        events[++i](cb, data)
                    } else {
                        events[++i](middleFn, data)
                    }
                } else {
                    throw new Error({message: error})
                }
            }
            events[0](middleFn)
        }
    },
    parallel(events) {
        return function(cb) {
            events.forEach(fn => {
                fn(cb)
            })
        }
    },
    race(events) {
        return function (cb){
            var isDone = false
            var fnCall = function(err, data) {
                if( isDone ) {
                    return 
                }
                isDone = true
                cb(err, data)
            }
            events.forEach(fn => {
                fn(fnCall)
            })
        }
    }
 }

 module.exports = async

猜你喜欢

转载自blog.csdn.net/weixin_40821790/article/details/81170992