原型链辅助库核心是封装标准API操作原型链,提供安全、兼容的getPrototypeOf、hasInChain、setPrototypeOf等方法,禁用__proto__,防循环引用与冻结对象误操作。

实现一个原型链辅助库,核心是封装对 JavaScript 原型链的读取(getPrototypeOf、hasOwnProperty、in 操作等)和写入(setPrototypeOf、属性定义)操作,同时兼顾兼容性、可预测性和安全性。不推荐直接暴露 __proto__,应优先使用标准 API。
获取原型链信息
目标是安全、清晰地查询对象的原型关系与属性来源。
-
获取直接原型:用
Object.getPrototypeOf(obj),它比obj.__proto__标准且不可枚举,且在 null 原型对象上返回 null,行为确定。 -
检查属性是否在原型链上:区分自有属性与继承属性。
obj.hasOwnProperty(prop)判断自有;prop in obj或Object.prototype.hasOwnProperty.call(obj, prop)配合Object.getPrototypeOf递归遍历可判断归属层级。 -
获取完整原型链:从对象开始,逐级调用
Object.getPrototypeOf,直到返回null为止。注意避免循环(如被恶意篡改的原型链),可加深度限制(如 100 层)或已访问对象 Set 缓存防环。
设置原型链
修改原型应谨慎,仅在必要时使用,并提供降级或提示机制。
-
设置直接原型:首选
Object.setPrototypeOf(obj, proto)。它会触发内部 [[Prototype]] 修改,且现代引擎已优化性能。避免赋值obj.__proto__ = proto,因非标准、部分环境(如 strict 模式下某些旧版 Safari)可能报错或静默失败。 -
创建带指定原型的新对象:用
Object.create(proto, properties)更安全可控。可一次性设定原型 + 自有属性描述符,避免后续多次 setPrototypeOf。 -
不可变原型防护:若目标对象被冻结(
Object.isFrozen(obj) === true),setPrototypeOf会静默失败(非严格模式)或抛错(严格模式)。库中应主动检测并给出明确提示,而非掩盖错误。
属性访问与代理增强(可选但实用)
单纯操作原型链常服务于更高级的属性访问逻辑,比如模拟“深度 get/set”或拦截继承行为。
-
安全读取链上属性:封装类似
get(obj, 'a.b.c')的函数,内部用Object.hasOwn(或兼容hasOwnProperty)+Object.getPrototypeOf逐级查找,跳过 undefined 中间值,避免报错。 -
只读/不可配置属性识别:结合
Object.getOwnPropertyDescriptor检查目标属性的writable、configurable、enumerable,再决定是否允许覆盖或重新定义。 -
避免污染原生原型:库自身绝不向
Object.prototype或Function.prototype添加方法,所有功能通过独立函数暴露,如proto.getChain(obj)、proto.set(obj, proto)。
基础实现示例(精简版)
以下是一个轻量、无依赖的核心骨架:
const proto = {
getPrototypeOf(obj) {
return Object.getPrototypeOf(obj);
},
getChain(obj) {
const chain = [];
let curr = obj;
const seen = new Set();
while (curr !== null && !seen.has(curr)) {
seen.add(curr);
chain.push(curr);
curr = Object.getPrototypeOf(curr);
}
return chain;
},
setPrototypeOf(obj, proto) {
if (Object.isFrozen(obj)) {
throw new Error('Cannot set prototype on frozen object');
}
return Object.setPrototypeOf(obj, proto);
},
hasInChain(obj, key) {
for (let o = obj; o != null; o = Object.getPrototypeOf(o)) {
if (key in o) return true;
}
return false;
}
};
它不侵入全局,不依赖 Proxy,兼容 ES5+ 环境,适合作为底层工具模块被其他框架或工具复用。

















