为什么我的Array.prototype.equals函数显示为使用jQuery.extend()复制的数组中的元素?

时间:2014-10-31 02:11:16

标签: javascript jquery arrays prototype

在我的程序中,我添加了this SO post中列出的Array.prototype.equals()函数。

我有以下功能来执行数组的深层复制(我严格用于记录目的 - 这样我就可以在Chrome控制台的各个时间点看到我的数组的样子。)

function deepCopy(array) {
    return $.extend(true, [], array);
}

然后我这样使用它:

console.log("Sorting metrics list by metric name...");
console.log("Metrics list before sort:");
console.log(deepCopy(metrics));
metrics.sort(compare);
console.log("Metrics list after sort:");
console.log(deepCopy(metrics));

作为参考,我的比较功能是:

function compare(a, b) {
  return a.name.localeCompare(b.name);
}

当我在deepCopy()之后在Chrome控制台中查看我的metrics数组时,为Array.prototype定义的equals方法是在数组中!图片:

enter image description here

从屏幕截图中可以看出,我检查了一切运行后的metrics数组的实际值,它显然不包含equals方法。这是我的理由,认为它与jQuery()。extends处理复制数组的方式有关。

有关如何修复我的deepCopy函数以阻止此操作的任何想法? (或者,如果需要,可以更改我的原型功能。)

1 个答案:

答案 0 :(得分:2)

这里有两个问题:

  • 您在Array原型上添加了一个可枚举的属性
  • 控制台奇怪:console.log与表达式评估不同

$.extends遍历源对象的所有可枚举属性,并将它们添加为目标对象的自己的实例属性(不是继承的属性)。如果使您的原型属性不可枚举,则不会将其直接复制到目标:

Object.defineProperty(Array.prototype, "equals", {
    enumerable: false,
    value: function(array) { /* ... */ }
});

(请参阅一些有用的阅读材料:Don’t modify objects you don’t own。)

您在控制台中键入metrics的最终测试不会显示equals属性,但它实际上仍然存在。考虑Chrome中的以下控制台会话,我们在Array原型上添加一个可枚举属性,然后使用带有$.extends的数组:

> Array.prototype.foo = "egg";
"egg"

> $.extend(true, [], ['bar', 'baz'])
["bar", "baz"]

> console.log($.extend(true, [], ['bar', 'baz']))
["bar", "baz", foo: "egg"] 

> Object.getOwnPropertyNames( $.extend(true, [], ['bar', 'baz']) )
["0", "1", "length", "foo"]

非索引属性仅在我们明确使用console.log时显示;当我们只评估表达式时,它们不显示,即使getOwnPropertyNames确认它们在那里。