面试题答案
一键面试潜在问题
- 浏览器兼容性:不同浏览器对对象可扩展能力的支持存在差异,特别是在旧版本浏览器中,可能对
Object.preventExtensions
、Object.seal
、Object.freeze
等方法支持不完善或存在行为差异。 - 原型链干扰:在处理对象可扩展能力时,可能意外影响原型链上属性的访问和修改。例如,若错误地对原型对象设置为不可扩展,可能导致所有继承自该原型的对象都无法添加新属性,即使在实例对象层面尝试处理可扩展性也无效。
- 属性特性冲突:对象属性具有多种特性,如
configurable
、enumerable
、writable
等。在处理可扩展能力时,可能会与这些属性特性产生冲突。比如,若将一个对象设置为不可扩展,再试图修改原型链上一个configurable
为false
的属性,可能会导致错误。
解决方案
- 检测环境支持:
if (typeof Object.preventExtensions!== 'function') { Object.preventExtensions = function (obj) { // 自定义实现逻辑 Object.defineProperty(obj, '__proto__', { value: Object.getPrototypeOf(obj), writable: false, configurable: false, enumerable: false }); return obj; }; } if (typeof Object.seal!== 'function') { Object.seal = function (obj) { Object.preventExtensions(obj); const propNames = Object.getOwnPropertyNames(obj); propNames.forEach(name => { Object.defineProperty(obj, name, { configurable: false }); }); return obj; }; } if (typeof Object.freeze!== 'function') { Object.freeze = function (obj) { Object.seal(obj); const propNames = Object.getOwnPropertyNames(obj); propNames.forEach(name => { Object.defineProperty(obj, name, { writable: false }); }); return obj; }; }
- 处理对象可扩展能力:
const proto = { prop: 'proto value' }; const obj = Object.create(proto); // 处理可扩展能力兼容性 Object.preventExtensions(obj); // 保证原型链上属性的正常访问和修改 console.log(obj.prop); // 正常访问原型链上属性 proto.prop = 'new proto value'; console.log(obj.prop); // 原型链上属性修改后,实例对象可正常获取新值
通过上述方法,先对环境进行检测并提供兼容性实现,然后在通过 Object.create
创建的对象上设置可扩展能力,同时能确保原型链上属性的正常访问和修改。