aliexpress前端算法面试总结

399 阅读3分钟

题目1:

const input = {
    a: 1,
    b: [1, 2, { c: true }, [3]],
    d: { e: 2, f: 3 },
    g: null,
}
function flatten(input) {
    // 需要实现的代码

}


console.log(flatten(input));
// 返回
// {
//     "a": 1,
//     "b[0]": 1,
//     "b[1]": 2,
//     "b[2].c": true,
//     "b[3][0]": 3,
//     "d.e": 2,
//     "d.f": 3,
//     // "g": null,  值为null或者undefined,丢弃
// }

这道题是在深拷贝的基础上记录下key的层级,下面的答案中附上生拷贝和防止爆栈的优化答案


const input1 = {
    a: 1,
    b: [1, 2, { c: true }, [3]],
    d: { e: 2, f: 3 },
    g: null,
}

function flatten(input) {
    // 需要实现的代码

    let res = arguments[1] ? arguments[1] : {};
    let keyStr = arguments[2] ? arguments[2] : '';
    if (Reflect.toString.call(input) === '[object Array]') {

        input.forEach((item, index) => {
            if (typeof item === 'object') {

                flatten(item, res, `${keyStr}[${index}]`)
            } else {
                res[`${keyStr}[${index}]`] = item
            }
        })
    } else {
        for (let key in input) {
            let tmp = keyStr ? `${keyStr}.${key}` : key;
            if (typeof input[key] === 'object') {
                flatten(input[key], res, tmp)
            } else {
                res[tmp] = input[key]
            }
        }
    }
    return res
}



function deepClone(obj) {//深拷贝

    let finObj = arguments[1] ? arguments[1] : {};
    for (let i in obj) {
        if (typeof obj[i] === 'object') {
            finObj[i] = obj[i] instanceof Array ? [] : {};
            deepClone(obj[i], finObj[i])
        } else {
            finObj[i] = obj[i]
        }

    }

    return finObj
}

//都做下尾递归优化处理(转成循环), 防止爆栈

function tco(fn) {
    let active = false;
    let argumentsArr = [];
    let value;

    return function () {

        if (!active) {
            argumentsArr.push(arguments);
            while (argumentsArr.length) {
                value = fn.apply(this, argumentsArr.shift());
                active = true;
            }
        }
        active = false;
        return value;
    }
}


let _faltten = tco(function (input) {
    let res = arguments[1] ? arguments[1] : {};
    let keyStr = arguments[2] ? arguments[2] : '';
    if (Reflect.toString.call(input) === '[object Array]') {

        input.forEach((item, index) => {
            if (typeof item === 'object') {

                _faltten(item, res, `${keyStr}[${index}]`)
            } else {
                res[`${keyStr}[${index}]`] = item
            }
        })
    } else {
        for (let key in input) {
            let tmp = keyStr ? `${keyStr}.${key}` : key;
            if (typeof input[key] === 'object') {
                _faltten(input[key], res, tmp)
            } else {
                res[tmp] = input[key]
            }
        }
    }
    return res
})

let _deepClone = tco(function(obj) {
    //let finObj = arguments[1] ? arguments[1] : {};
    let finObj
    if (arguments[1]) {
      finObj = arguments[1]
    } else {
      // console.log('obj,', obj)
      if (obj instanceof Array === true) {//第一次的时候是什么结构就返回什么解构
        finObj = []
      } else {
        finObj = {}
      }
    }    
    for (let i in obj) {
        if (typeof obj[i] === 'object') {
            finObj[i] = obj[i] instanceof Array ? [] : {};
            _deepClone(obj[i], finObj[i])
        } else {
            finObj[i] = obj[i]
        }

    }

    return finObj
})

console.log(_flatten(input1));//扁平化的结果
console.log(_deepClone(input1));//深拷贝的结果

题目2


// 8. 实现一种自定义事件机制:
class EventEmitter {
    /* 在此处填写实现 */

}
const emitter = new EventEmitter();
const handler = function (evt) {
    console.log(1, evt);
};

emitter.on('foo', handler);
emitter.once('foo', function (evt) {
    console.log(2, evt);
});
emitter.fire({ type: 'foo', value: 'hello' });
emitter.fire({ type: 'foo', value: 'world' });
emitter.off('foo', handler);
emitter.fire({ type: 'foo', value: 'test' });
// 实现如下方法:
// 1. on,添加事件,可以给某个事件添加多个处理函数,这些函数可以被多次触发
// 2. once,添加一次性事件,在触发过一次之后不再触发
// 4. fire,触发特定事件
// 5. off,移除特定的事件处理函数

答案


// 8. 实现一种自定义事件机制:
class EventEmitter {
    /* 在此处填写实现 */

    constructor() {
        this.target = {};
    }
    on(type, handler) {
        this.target[type] = this.target[type] || [];
        this.target[type].push(handler);
    }
    off(type, handler) {
        let self = this;
        this.target[type] = this.target[type] || [];
        this.target[type].splice(self.target[type].indexOf(handler), 1);
    }
    fire({type, value}) {
        this.target[type].forEach((item, index, arr) => {
            item.call(this, value);
        })
    }
    once(type, handler) {
        let self = this;
        function fn() {
            handler.apply(this, arguments)
            self.off(type, handler)
        }
        this.on(type, fn);
    }
}
const emitter = new EventEmitter();
const handler = function (evt) {
    console.log(1, evt);
};
const handler2 = function (evt) {
    console.log('handler2', evt);
};
const handler3 = function (evt) {
    console.log('handler3', evt);
};
emitter.on('foo', handler);
emitter.on('foo', handler2);
emitter.on('foo', handler3);
emitter.once('foo', function (evt) {
    console.log(2, evt);
});
emitter.fire({ type: 'foo', value: 'hello' });
// emitter.fire({ type: 'foo', value: 'world' });
// emitter.off('foo', handler);
// emitter.fire({ type: 'foo', value: 'test' });
// 实现如下方法:
// 1. on,添加事件,可以给某个事件添加多个处理函数,这些函数可以被多次触发
// 2. once,添加一次性事件,在触发过一次之后不再触发
// 4. fire,触发特定事件
// 5. off,移除特定的事件处理函数