object.create不会拷贝自有accessor属性,因其仅设置[[prototype]]而不处理对象自身属性;需用object.getownpropertydescriptors获取描述符,再用object.defineproperties手动定义到新对象上。

用 Object.create(Object.getPrototypeOf(obj)) 可以创建一个新对象,其原型链与原对象一致,从而继承所有定义在原型上的 getter/setter。但这只是“继承”而非“复制”——它不会把原对象自身属性(包括自有 getter/setter)拷贝过去。
为什么 Object.create 不会拷贝自有 accessor 属性
Object.create 只设置新对象的 [[Prototype]],不处理 obj 自身的属性。如果 getter/setter 是定义在对象自身(而非原型)上,比如通过 Object.defineProperty(obj, 'x', { get() { ... }, set(v) { ... } }),那它们不会自动出现在新对象上。
如何保留自有 getter/setter 的浅拷贝
需要两步:先用 Object.create 复制原型链,再手动遍历并重新定义自有 accessor 属性:
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
- 用
Object.getOwnPropertyDescriptors(obj)获取对象自身所有属性的完整描述符(含get、set、enumerable、configurable等) - 用
Object.defineProperties(newObj, descriptors)把这些描述符应用到新对象上 - 确保新对象的原型正确:传入
Object.getPrototypeOf(obj)给Object.create
示例:
function shallowCloneWithAccessors(obj) {
const proto = Object.getPrototypeOf(obj);
const descriptors = Object.getOwnPropertyDescriptors(obj);
const clone = Object.create(proto);
Object.defineProperties(clone, descriptors);
return clone;
}
<p>// 使用
const source = {
_value: 100
};
Object.defineProperty(source, 'value', {
get() { return this._value * 2; },
set(v) { this._value = v / 2; },
configurable: true,
enumerable: true
});</p><p>const copy = shallowCloneWithAccessors(source);
console.log(copy.value); // 200
copy.value = 40;
console.log(copy._value); // 20</p>注意原型链和属性可配置性
如果原对象的 accessor 属性是 configurable: false,你仍能成功定义到新对象上(因为新对象尚未拥有该属性),但后续无法 delete 或 redefine。如果原对象的原型上也有 accessor,它们会自然继承,无需额外操作——前提是没被自有属性遮蔽。
不适用于不可扩展或冻结对象
如果 obj 被 Object.preventExtensions()、Object.seal() 或 Object.freeze(),Object.getOwnPropertyDescriptors 仍能读取 accessor 描述符,但 Object.defineProperties 在冻结对象上会失败。此时应先检查 Object.isFrozen(obj),必要时只克隆可写的子集或抛出提示。










