如何克隆任何对象,包括特殊类型?
How to clone any object, including special types?
我需要编写一个 returns 对象克隆的函数。
类似于:
// non recursive clone
function clone( obj ) {
const newObj = Object.create( Object.getPrototypeOf(obj) );
return Object.assign( newObj, obj );
}
这当然只适用于对象,不适用于基本类型:它不适用于 undefined
、null
、布尔值、数字、字符串、符号。
...但它也不适用于其他类型,例如Array
, Set
, Map
.
我想支持尽可能多的类型,我最好的办法是逐个处理 特殊 类型。
我认为带有 Internal Methods or Internal Slots 的对象可能会产生问题。我不太确定这一点,我找不到包含内部方法或插槽的标准类型列表。
Object.create()
不能正确创建哪些标准类型?
Which standard types cannot correctly be created by Object.create()
exactly?
确实是全部。您谈论的那些特殊类型只能使用 new
或 Reflect.construct
创建,提供将创建内部插槽的内置构造函数。
I could not find a list of standard types with Internal Methods or Slots.
它就在规范中,chapter 9 Exotic Objects(对于内部方法)。您可以很好地处理普通对象(Object.create
创建一个),但是您会遇到函数对象、绑定函数对象、数组对象、字符串对象、参数对象、类型化数组对象、模块名称空间对象和代理的问题。此外,您可以通过搜索 OrdinaryCreateFromConstructor(Generator
、Boolean
、Error
和所有其他本机错误的用法来查找具有特殊内部插槽的对象, Number
, Date
, RegExp
, Map
, Set
, WeakMap
, WeaskSet
, ArrayBuffer
, DataView
, Promise
) 和 ObjectCreate (ListIterator
, Arguments
, 所有类型数组, StringIterator
, ArrayIterator
, MapIterator
, SetIterator
).
I'd like to support as many types as I can
您应该决定(并记录)哪些受支持,哪些不受支持。特别是对于递归克隆来说,这将是一件麻烦事。还要确保记录您如何处理不可枚举或符号键控的自有属性和 getters/setters,默认的 Object.assign
行为可能不是您想要的。
how to do this is handling special types case by case?
我会在所有支持类型的原型上定义一个 Symbol.for("clone")
方法,这样很容易扩展。可能在不支持克隆的情况下使用已知值代替 and/or 默认复制算法没有意义,例如在迭代器或函数对象上,以便可以使用错误消息处理或忽略它们。
我需要编写一个 returns 对象克隆的函数。
类似于:
// non recursive clone
function clone( obj ) {
const newObj = Object.create( Object.getPrototypeOf(obj) );
return Object.assign( newObj, obj );
}
这当然只适用于对象,不适用于基本类型:它不适用于 undefined
、null
、布尔值、数字、字符串、符号。
...但它也不适用于其他类型,例如Array
, Set
, Map
.
我想支持尽可能多的类型,我最好的办法是逐个处理 特殊 类型。
我认为带有 Internal Methods or Internal Slots 的对象可能会产生问题。我不太确定这一点,我找不到包含内部方法或插槽的标准类型列表。
Object.create()
不能正确创建哪些标准类型?
Which standard types cannot correctly be created by
Object.create()
exactly?
确实是全部。您谈论的那些特殊类型只能使用 new
或 Reflect.construct
创建,提供将创建内部插槽的内置构造函数。
I could not find a list of standard types with Internal Methods or Slots.
它就在规范中,chapter 9 Exotic Objects(对于内部方法)。您可以很好地处理普通对象(Object.create
创建一个),但是您会遇到函数对象、绑定函数对象、数组对象、字符串对象、参数对象、类型化数组对象、模块名称空间对象和代理的问题。此外,您可以通过搜索 OrdinaryCreateFromConstructor(Generator
、Boolean
、Error
和所有其他本机错误的用法来查找具有特殊内部插槽的对象, Number
, Date
, RegExp
, Map
, Set
, WeakMap
, WeaskSet
, ArrayBuffer
, DataView
, Promise
) 和 ObjectCreate (ListIterator
, Arguments
, 所有类型数组, StringIterator
, ArrayIterator
, MapIterator
, SetIterator
).
I'd like to support as many types as I can
您应该决定(并记录)哪些受支持,哪些不受支持。特别是对于递归克隆来说,这将是一件麻烦事。还要确保记录您如何处理不可枚举或符号键控的自有属性和 getters/setters,默认的 Object.assign
行为可能不是您想要的。
how to do this is handling special types case by case?
我会在所有支持类型的原型上定义一个 Symbol.for("clone")
方法,这样很容易扩展。可能在不支持克隆的情况下使用已知值代替 and/or 默认复制算法没有意义,例如在迭代器或函数对象上,以便可以使用错误消息处理或忽略它们。