2017-06-05 40 views
0

,我需要写一个返回一个对象的克隆功能。如何克隆任何对象,包括特殊类型?

喜欢的东西:

// 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()

+0

在我看来,为什么'Object.create'会创建除了对象之外的其他东西? – evolutionxbox

+0

@evolutionxbox:'Array','Set','Map'等都是对象。 JavaScript中只有7种[数据类型](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures);该文件明确指出:“数组是常数对象,整数键属性和'length'属性之间存在特定关系。”最后'typeof [] ===“object”'。 – peoro

+0

虽然这是真的,但每种对象类型都有特殊的属性。数组有'长度',但是当使用'assign'时这个没有设置。您可能必须为每个“类型”创建自定义“分配”。 – evolutionxbox

回答

1

哪些标准类型不能正确创建Object.create()

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

我找不到内部方法或插槽的标准类型列表。

这是正确的,在规范,chapter 9 Exotic Objects(用于内部方法)。你可以对待ordingary对象就好(Object.create创建一个),但是你会遇到函数对象,绑定函数对象,数组对象,字符串对象,参数对象,TypedArray对象,模块名称空间对象和代理的问题。此外,您还可以通过搜索DataViewOrdinaryCreateFromConstructorGeneratorBooleanError惯例和所有其他本地错误,NumberDateRegExpMapSetWeakMapWeaskSetArrayBuffer,找到特殊的内部插槽的对象,Promise )和ObjectCreateListIterator, Arguments,所有类型的阵列,StringIterator,ArrayIterator,MapIterator,SetIterator)。

我想这是支持和不支持多种类型的,因为我可以

你应该决定(和文件)。特别是对于递归克隆来说,这将是一件麻烦事。还要确保记录如何处理不可枚举或符号键属性和getter/setter,默认Object.assign行为可能不是所需的行为。

如何处理特殊类型的情况?

我想对所有支持的类型的原型定义Symbol.for("clone")方法,这样很容易扩展。如果不支持克隆和/或默认的复制算法没有意义,则可能使用已知值,例如,在迭代器或函数对象上,以便可以使用错误消息处理这些对象或将其忽略。

+0

我看了所有提到OrdinaryCreateFromConstructor的类型,我可以找到Boolean,Error,NativeError,Number,Date,RegExp,Map,Set,WeakMap WeakSet,ArrayBuffer,DataView,Promise。你能否验证这些类型加上你提到的外来对象是否是一个标准对象类型的完整列表,它们不能用Object.create正确工作? – peoro

+0

是的,这些都是我发现的。 – Bergi