模拟环境
// 如何判断原型链上重复的属性
// 模拟一个原型链 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]]
很久很久以前,在一次面试中,面试官问了我这样一个奇怪的问题,这个问题一直萦绕在脑袋里面,所以将他写下来。