如果某人想为旧浏览器实现函数(例如Array.prototype.filter
)哪种方法更好?为什么?每个人的利弊是什么?
if (!Array.prototype.filter) {
Array.prototype.filter = function() {
//implementation
}
}
或
function myFilter(e,i,f) {
if (!Array.prototype.filter) {
//implementation
} else {
return Array.prototype.filter(e,i,f);
}
}
就个人而言,我大部分时间都使用第一种方法(添加Array.prototype.filter
),但是有时我不这样做。在为旧浏览器编写大型框架时,我不使用第一种方法,这些浏览器需要在互联网上使用任何其他脚本,包括不良的浏览器。
这是要考虑的事情。假设您使用所描述的方法在Array.prototype.filter
中进行了垫子,然后将第三方脚本添加到您的网站上执行类似的操作:
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
循环迭代阵列,但是您无法控制第三方脚本可能会做什么。这是主要的缺点,当您编写一个大规模库以在互联网上使用时,值得考虑。
这使您无法将任何内容添加到 Object.prototype
,perique.prototype.method = function(){...} assignment), because
for ... in is good to use on other types of objects, and this kind of shimming breaks
for ... in ... in。
但是,如果您只是在自己的网站上编写代码,并且您知道您将列出的脚本是高质量的,并且不要像这样造成失误,那是一种很好的技术。
此外,如果您的代码仅针对ECMAScript 5符合条件5的浏览器,则可以将垫片定义为不可操的,这将阻止它们在for...in
循环中显示。我目前正在从事一个项目,以在ES5浏览器中使用Ecmascript 6方法,并且由于仅打算在ES5浏览器中运行,因此我可以逃脱:
Object.defineProperty(Array.prototype, 'contains', {
value: function(value) {
// Implementation
},
enumerable: false,
writable: true,
configurable: true
});
以这种方式定义垫片可以防止其在for...in
循环中显示,因此在Object.prototype
上使用的甚至可以安全地使用您的实现,请遵循Spec/Draft 。
提出了次要点。如果您不信心根据规格准确地实现该方法,那么您也最好不要使用它。这可能会破坏库的库,这些库会检查内置并在可用的情况下使用它否则不是。比实施破裂更好地没有任何事情。
正是由于这个原因,我永远不会尝试部分实施垫片。例如,Object.create
不能在ES3浏览器中完全实现,因此我永远不会涂抹它。我只使用自己的myLibrary.create
函数,该功能的功能可能相似,但是至少可以检查存在Object.create
的存在的任何代码并没有被误导以为它具有完整的,有效的版本。
故事的寓意:如果您要去垫片,请查看一些非常出色的,规格的符合MDN的垫片,然后学会像它一样编写代码:array.prototype.filter
最后一个说明:许多库不在Array.prototype
上的方法中,其中一些考虑因素可能部分是原因,但是在许多情况下,也有一个历史原因。在 filter
是一种标准内置方法之前,正在开发诸如jQuery之类的库。Prototype.js采用了添加非标准方法的方法,该方法的缺点比上面讨论的要多。jQuery决定不在内置的原型中添加非标准方法,这就是为什么它们具有$.filter
。
第二种方法更常见;它被诸如jQuery和underscore.js之类的流行Shim JS库使用。
说,扩展本地对象危险要比扩展 host对象 (后者,它是典型的'catch 22':您将它们扩展为在浏览器无法很好地处理主机对象的扩展)。本文总结了:
不要忘记编写适当的,合规的垫片很难。何时在 疑问,使用独立对象。当您的方法是一部分时 未完成的规格,使用独立对象。只有当你 确定方法合规性和方法是完成的一部分, 未来的防护规范,直接涂抹本地物体是安全的吗?
对于新的标准JS功能,班级最佳实践是在闪烁,如果在旧浏览器上找不到该功能,则扩展了类。
但是,如果该函数没有成为标准的最佳实践是创建新功能,并且不更改标准类,因为如果您使用以后可能会使用不同行为使用的函数名称,它将破坏您的应用程序。