如何克隆任何对象,包括特殊类型?

时间:2017-06-05 09:41:32

标签: javascript ecmascript-6 clone

我需要编写一个返回对象克隆的函数。

类似的东西:

// non recursive clone
function clone( obj ) {
  const newObj = Object.create( Object.getPrototypeOf(obj) );
  return Object.assign( newObj, obj );
}

这当然只适用于对象,而不适用于原始类型:它不适用于undefinednull,布尔值,数字,字符串,符号。

...但它也不适用于其他类型,例如ArraySetMap

我想支持尽可能多的类型,我对如何执行此操作的最佳想法是逐个处理特殊类型。

我认为Internal Methods or Internal Slots的对象可能会产生问题。我不完全确定这一点,我找不到内部方法或插槽的标准类型列表。

Object.create()无法正确创建哪些标准类型?

1 个答案:

答案 0 :(得分:1)

  

Object.create()无法正确创建哪些标准类型?

所有这些,的确如此。您谈论的那些特殊类型只能使用newReflect.construct创建,提供将创建内部插槽的内置构造函数。

  

我找不到包含内部方法或老虎机的标准类型列表。

它就在规范chapter 9 Exotic Objects中(对于内部方法)。你可以很好地处理ordingary对象(Object.create创建一个),但是你会遇到Function对象,Bound Function对象,Array对象,String对象,Arguments对象,TypedArray对象,Module命名空间对象和Proxies的问题。此外,您可以通过搜索 OrdinaryCreateFromConstructor GeneratorBooleanError以及所有其他本机错误{{{}的用法来查找具有特殊内部插槽的对象1}},NumberDateRegExpMapSetWeakMapWeaskSet,{{1} },ArrayBuffer)和 ObjectCreate DataViewPromise,所有类型数组,ListIteratorArguments,{{1} },StringIterator)。

  

我想支持尽可能多的类型

您应该决定(并记录)哪些是受支持的,哪些不受支持。特别是对于递归克隆,这将是一个麻烦。还要确保记录如何处理不可枚举或符号键控的自有属性和getter / setter,默认的ArrayIterator行为可能不是所需的行为。

  

如何做到这一点是逐个处理特殊类型?

我在所有支持的类型的原型上定义了一个MapIterator方法,这样很容易扩展。可能使用已知值而不是支持克隆和/或默认复制算法没有意义,例如,在迭代器或函数对象上,以便可以使用错误消息处理它们或忽略它们。

相关问题