就个人而言,我大部分时间都使用第一种方法(添加Array.prototype.filter
),但有时我不使用。在为旧浏览器编写大型框架时,我不使用第一种方法,它需要与 Internet 上的任何其他脚本(包括坏脚本)配合使用。
以下是需要考虑的事项。假设您Array.prototype.filter
使用您描述的方法进行填充,然后向您的网站添加一个 3rd 方脚本,该脚本执行以下操作:
var someArray = [ 'a', 'b', 'c' ];
console.log('The first three letters of the alphabet are: ');
for (var i in someArray)
console.log(someArray[i]);
结果?
The first three letters of the alphabet are:
a
b
c
function () { ... }
您的过滤器功能被打印出来!现在,在技术层面上,没有人应该使用循环来迭代数组for...in
,但是您无法控制 3rd 方脚本可能会做什么。这是主要的缺点,当您编写一个在整个 Internet 上使用的大型库时,值得考虑。
这可以防止您在Object.prototype
句号中添加任何内容(使用简单的 Object.prototype.method = function() { ... } assignment), because
for...in is good to use on other types of objects, and this kind of shimming breaks
for...in`。
但是,如果您只是编写要在您自己的网站上使用的代码,并且您知道您将包含的脚本质量很高,并且不会犯这样的错误,那么这是一种很好的技术。
此外,如果您的代码仅适用于兼容 ECMAScript 5 的浏览器,您可以将 shim 定义为不可枚举,这将防止它们出现在for...in
循环中。我目前正在开发一个项目,以在 ES5 浏览器中使用 ECMAScript 6 方法填充,因为它只打算在 ES5 浏览器中运行,所以我可以摆脱:
Object.defineProperty(Array.prototype, 'contains', {
value: function(value) {
// Implementation
},
enumerable: false,
writable: true,
configurable: true
});
以这种方式定义 shim 可以防止它出现在for...in
循环中,因此在 上使用它甚至是安全的Object.prototype
,前提是您的实现准确地遵循 spec/draft。
这带来了第二点。如果您不确定是否可以按照规范准确实现该方法,最好不要填充它。这可能会破坏检查内置并在可用时使用它的库,但会退回到某些东西否则,如果不是。最好让他们一无所有,而不是使用损坏的实现。
正是出于这个原因,我从不尝试部分实现 shim。例如,Object.create
不能在 ES3 浏览器中完全实现,所以我永远不会填充这个。我只是使用我自己的myLibrary.create
函数,它的功能可能类似,但至少任何可以检查是否存在的代码Object.create
都不会被误导相信它有一个完整的工作版本。
故事的寓意:如果您要进行 shim,请查看 MDN 上一些非常棒的、符合规范的 shim,并学习编写类似的代码:Array.prototype.filter
最后一点:许多库不在方法中填充的原因Array.prototype
可能部分是出于这些考虑,但在许多情况下也有历史原因。像 jQuery 这样的库之前 正在开发,filter
是一种标准的内置方法。Prototype.js 采取了添加非标准方法的方法,这比上面讨论的缺点更多。jQuery 决定不向内置原型添加非标准方法,这就是它们具有$.filter
.