扩展类或创建新功能,这更好



如果某人想为旧浏览器实现函数(例如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功能,班级最佳实践是在闪烁,如果在旧浏览器上找不到该功能,则扩展了类。

但是,如果该函数没有成为标准的最佳实践是创建新功能,并且不更改标准类,因为如果您使用以后可能会使用不同行为使用的函数名称,它将破坏您的应用程序。

最新更新