如何判断原型链上重复的属性?

模拟环境

// 如何判断原型链上重复的属性
// 模拟一个原型链 Baz => Bar => Foo => FooProto => Object => null
const FooProto = {
    ak: 1
}
const Foo = Object.create(FooProto)
Foo.ak = 2
Foo.aj = 4
const Bar = Object.create(Foo)
Bar.ak = 3
Bar.aj = 5
Bar.am = 7
const Baz = Object.create(Bar)

解答

/**
 * @method collProtoAttrs
 * @description 收集对象原型链上重复的属性
 * @param {Object} obj 目标对象
 * @return {Array} [[${key}, ${count}],...]
*/
function collProtoAttrs (obj) {
    let lastProto = Object.getPrototypeOf(obj)
    const isRepeatAttrs = new Map()
    while (lastProto !== null) {
        Object.keys(lastProto).forEach(k => {
            if (isRepeatAttrs.has(k)) {
                isRepeatAttrs.set(k, isRepeatAttrs.get(k) + 1)
            } else {
                isRepeatAttrs.set(k, 1)
            }
        })
        lastProto = Object.getPrototypeOf(lastProto)
    }
    // 列出所有属性名及出现的次数,过滤次数大于一的属性即为重复的属性。
    // console.log(isRepeatAttrs) // {${key} => count} ...
    return [...isRepeatAttrs].filter(([, count]) => count > 1) // [[${key}, ${count}],...]
}

console.log(collProtoAttrs(Baz)) // [["ak",3],["aj",2]]

很久很久以前,在一次面试中,面试官问了我这样一个奇怪的问题,这个问题一直萦绕在脑袋里面,所以将他写下来。

发表评论

您的电子邮箱地址不会被公开。