将自定义函数添加到Array.prototype中

Mat*_*ias 49 javascript arrays internet-explorer

我正在开发一个支持AJAX的asp.net应用程序.我刚刚为Array.prototype添加了一些方法

Array.prototype.doSomething = function(){
   ...
}
Run Code Online (Sandbox Code Playgroud)

这个解决方案对我有用,可以以"漂亮"的方式重用代码.

但是当我测试它与整个页面一起工作时,我遇到了问题.我们有一些自定义的ajax扩展器,并且它们开始表现为意外:一些控件在其内容或值周围显示"未定义".

可能是什么原因?我错过了修改标准对象原型的一些内容吗?

注意:我很确定在修改Array的原型时错误就开始了.它应该只与IE兼容.

tho*_*ter 48

修改内置对象原型通常是一个坏主意,因为它总是有可能与同一页面上的其他代码冲突.

在Array对象原型的情况下,这是一个特别糟糕的主意,因为它有可能干扰迭代任何数组成员的任何代码段,例如for .. in.

为了说明一个例子(从这里借来):

Array.prototype.foo = 1;

// somewhere deep in other javascript code...
var a = [1,2,3,4,5];
for (x in a){
    // Now foo is a part of EVERY array and 
    // will show up here as a value of 'x'
}
Run Code Online (Sandbox Code Playgroud)

最好使用doSomething函数创建自己类型的对象构造函数,而不是扩展内置数组.


编辑:重复我在评论中的内容:

反之亦然 - 你应该避免使用..如果某些n00b修改了Array原型,你应该避免修改Array原型,以防某些n00b在数组上使用for..in.;)

此外,现在存在Object.defineProperty扩展对象原型而不使新属性可枚举的一般方法,尽管我仍然不会将其用作扩展内置类型的理由,因为即使此外Object.defineProperty仍有可能与其他冲突其他脚本.考虑有人为您的代码提供代码,然后将两个版本放在同一页面上 - 您对Array对象的自定义增强功能是否仍然可以按预期工作?

  • 这些天的_right_答案是使用`Object.defineProperty(Array.prototype,'method',...)`这将使新方法_non-enumerable_. (35认同)
  • 我相信"for(x in y)"构造用于迭代对象的成员.对于数组的基于索引的迭代,我认为它不合适.但是,您关于干扰页面上其他代码的观点是有效的 - 特别是如果第三方库以这种方式使用for-in. (6认同)
  • 是的,反之亦然 - 你应该避免使用..以防一些n00b修改了Array原型,你应该避免修改Array原型,以防一些n00b在数组上使用for..in.;) (5认同)
  • 向内置原型添加方法时所面临的风险是,未来版本的 JavaScript 将实现具有相同名称的方法,然后您的代码将破坏依赖于内置行为的任何脚本,或者您的脚本将中断,因为您的 API 可能与内置 API 不兼容。 (3认同)
  • 坦率地说,`hasOwnProperty` 是一种不幸的解决方法,可以解决有人做了一些诸如修改 Array.prototype 之类的邪恶事情的可能性,并且在与第三方代码共存时是一个好主意。然而,这种变通方法的存在并不能证明这种做法是合理的(或使其不那么邪恶),并且修改内置对象原型还有其他副作用而不是它对 `for..in` 的影响。 (2认同)
  • 修改后的答案指出即使使用`Object.defineProperty` 修改内置类型仍然是一个坏主意,因为您仍然可能与其他代码发生冲突。 (2认同)

cse*_*lls 41

虽然与其他位置发生冲突的可能性代码覆盖原型上的函数仍然存在风险,但如果您想使用现代版本的JavaScript执行此操作,则可以使用Object.defineProperty方法,关闭可枚举位,例如

// functional sort
Object.defineProperty(Array.prototype, 'sortf', {
    value: function(compare) { return [].concat(this).sort(compare); }
});
Run Code Online (Sandbox Code Playgroud)

  • 不需要声明`enumerable:false`,因为`false`是`enumerable`的默认值. (3认同)
  • 它应该与 `Array.prototype.sortf = function(compare) { return [].concat(this).sort(compare); 相同 }` (2认同)

tik*_*ika 12

有一个警告!也许你这样做了:小提琴演示

让我们说一个返回第一个元素的数组和方法foo:

var myArray = ["apple","ball","cat"];

foo(myArray) // <- 'apple'

function foo(array){
    return array[0]
}
Run Code Online (Sandbox Code Playgroud)

以上是可以的,因为在解释时间内功能被提升到顶部.

但是,这不起作用:(因为原型未定义)

myArray.foo() // <- 'undefined function foo'

Array.prototype.foo = function(){
    return this[0]
}
Run Code Online (Sandbox Code Playgroud)

为此,只需在顶部定义原型:

Array.prototype.foo = function(){
    return this[0]
}

myArray.foo() // <- 'apple'
Run Code Online (Sandbox Code Playgroud)

是的!你可以覆盖原型!这是允许的.您甚至可以add为Arrays 定义自己的方法.