在我的程序中,我添加了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方法是在数组中!图片:
从屏幕截图中可以看出,我检查了一切运行后的metrics数组的实际值,它显然不包含equals方法。这是我的理由,认为它与jQuery()。extends处理复制数组的方式有关。
有关如何修复我的deepCopy函数以阻止此操作的任何想法? (或者,如果需要,可以更改我的原型功能。)
答案 0 :(得分:2)
这里有两个问题:
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
确认它们在那里。