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

Javascript 为什么我的Array.prototype.equals函数在使用jQuery.extend()复制的数组中显示为元素?,javascript,jquery,arrays,prototype,Javascript,Jquery,Arrays,Prototype,在我的程序中,我添加了中列出的Array.prototype.equals()函数 我有以下功能来执行阵列的深度复制(我严格地将其用于日志记录目的,这样我就可以在Chrome控制台的不同时间点上看到我的阵列的样子。) 然后我就这样使用它: console.log("Sorting metrics list by metric name..."); console.log("Metrics list before sort:"); console.log(deepCopy(metrics)); m

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

我有以下功能来执行阵列的深度复制(我严格地将其用于日志记录目的,这样我就可以在Chrome控制台的不同时间点上看到我的阵列的样子。)

然后我就这样使用它:

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);
}
当我在Chrome控制台的deepCopy()之后查看我的度量数组时,为array.prototype定义的equals方法就在数组中!图片:

正如您从屏幕截图中看到的,我在运行完所有内容后检查度量数组的实际值,它显然不包含equals方法。这就是我认为它与jQuery().extend如何处理复制数组有关的原因

关于如何修复我的deepCopy函数以停止此操作,有什么想法吗?(如果需要,也可以更改原型功能。)

这里有两个问题:

  • 您正在阵列原型上添加可枚举属性
  • 控制台奇怪之处:
    console.log
    与表达式求值不同
$。在源对象的所有可枚举属性上扩展
循环,并将它们添加为目标对象的自身实例属性(而不是继承属性)。如果使原型属性不可枚举,则不会将其直接复制到目标:

Object.defineProperty(Array.prototype, "equals", {
    enumerable: false,
    value: function(array) { /* ... */ }
});
(参见一些有用的阅读:)

在控制台中键入
metrics
的最终测试不会显示
equals
属性,但它实际上仍然存在。考虑Chrome中的以下控制台会话,其中在数组原型上添加可枚举属性,然后使用具有<代码> $的数组。扩展< /代码>:

> 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
确认了它们的存在,当我们只是计算表达式时,它们也不会出现。

撇开您的具体问题不谈,将东西附加到默认类型原型通常被认为是一个坏主意。这特别是因为您向
原型添加了一个方法。它与使用
$.extend
或您的
deepCopy
无关。将
prototype
方法添加到
Array
,创建一个新的数组,然后
console.log
it-您将看到它
JSON.stringify
.toString()
prototype
方法的默认可枚举性是枚举它,这就是它出现的原因。使用
Object.defineProperty
可以“修复”it@Ian:如他在问题中所示,使用
.extend
后,如果您使用
result.hasOwnProperty(“equals”)
您会得到一个
true
结果,因此jQuery显然在这个过程中包含了原型属性。@MatthewHerbst根据您计划如何使用数组,应该可以。从技术上讲,它似乎是在将原型
equals
方法作为一种方法复制到实际实例上。除了在复制的实例上,它什么都不做,只是“覆盖”了它的
prototype
方法(但它们引用了相同的函数)。只要您正常地处理数组(jQuery似乎没有这样做),您就应该很好……即使使用您已有的代码
console.log
工作正常-它显示了您添加到
prototype
@MatthewHerbst:…的可枚举属性……会有人试图用绝对术语说,您决不能修改像本机原型这样的对象。请注意,只要您接受了解这些修改的编码实践,就绝对没有理由进行这样的限制。
foo=“egg”
。。。这对我来说是新的。那是不是像蛋富英?
> 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"]