在JavaScript和Node.js中为String类添加函数的性能影响是什么?

在JavaScript中为String类添加函数有什么影响? 这是一个坏主意吗? 例如,

// String functions String.prototype.startsWith = function(string) { return (this.indexOf(string) === 0); } String.prototype.empty = function() { //console.log($.trim(this.valueOf())); if($.trim(this.valueOf()) == '') { return true; } else { return false; } } 

       

网上收集的解决方案 "在JavaScript和Node.js中为String类添加函数的性能影响是什么?"

那么首先原型比对象上的函数慢。 创build一个函数的代价和查找一样。 在原型上查找比在普通对象上花费更多

看看这个JSPerf: http ://jsperf.com/prototype-methods-vs-object-methods

这是设置:

 <script> Benchmark.prototype.setup = function() { function Bob() { } var b = new Bob(); Bob.prototype.testproto = function() {}; b.testobj = function() {}; }; </script> 

对象方法v原型

也就是说,在string原型上添加东西与将其添加到任何其他原型没有什么不同。

性能方面,没有影响。

但是,这还不是一个好主意。 你现在依赖于全局改变的状态。 如果其他模块做同样的事情会发生什么? 或者更糟的是,做一个稍微不同的事情,但使用相同的名字? 哎哟。

最好只定义带有String参数的函数,然后使用函数。

它没有performance的惩罚。 它不直接影响任何String对象,函数只绑定到String.prototype

不这样做的唯一原因是因为某处有人可能会使用for-in构造而不检查hasOwnProperty并且意外地迭代你的新函数。

如果不可能的话,你应该继续。

我build议编写自己的本地对象原型扩展库,这比这句话的第一句话可能提出的要简单得多。 Prototype.js做类似的事情,就像我在我维护的各种系统上使用的专有库一样。 这种方法的一个优点是可以兼容文库,另外一个优点是减less了不需要扩展方法时创build新的本地对象的开销。 一些像这样的库使用单个对象来扩展方法,我更喜欢有与特定的本地对象有关的对象。

 (function(){ //native object specific factory objects for expansion var Arrays = function(o) { this.value = o; }, , Objects = function(o) { this.value = o; }, , Strings = function(o) { this.value = o; }, , Functions = function(o) { this.value = o; }, , Dates = function(o) { this.value = o; }, , Numbers = function(o) { this.value = o; }; , Booleans = function(o) { this.value = o; }; //route object to correct expansion pack var Shell = function(o) { var type = Object.prototype.toString.call(o); switch( type ) { case '[object Array]' : return new Arrays(o); case '[object Boolean]' : return new Booleans(o); case '[object Date]' : return new Dates(o); case '[object Function]': return new Functions(o); case '[object Number]' : return new Numbers(o); case '[object Object]' : return new Objects(o); case '[object String]' : return new Strings(o); default : throw { name : "Unsupported Object", message: "Unsupported Object type: "+type}; } } //easy access for prototyping Shell.Array = Arrays.prototype; Shell.Boolean = Booleans.prototype; Shell.String = Strings.prototype; Shell.Function = Functions.prototype; Shell.Date = Dates.prototype; Shell.Number = Numbers.prototype; Shell.Object = Objects.prototype; //global access this._nativeWrapper = Shell; })(window); 

有几件事情你想添加到这个可能的方法链接和一次应用原型扩展到所有的工厂对象。 你还需要确保,如果你编写一个扩展器来将属性复制到Shell的原型或任何工厂对象上,那么这个对象就是以getter和setter方式来解释的。

在性能方面,向String原型添加方法与向任何其他对象添加方法没有区别。 我也跑了一些testing,并有一个自定义的方法,似乎并没有减缓任何原生的string方法的执行 – 即添加“someOtherFunc”到String.prototype不会导致“indexOf”运行速度较慢。

当然,你的JavaScript函数比那些原生版本要慢,所以如果你在旧浏览器中添加一个“trim”函数,那么那些具有本机trim函数的函数的运行速度比没有这个function的运行速度要快许多倍。 那不用说了。

正如其他人所指出的,当你为核心JavaScript对象的原型添加了太多的函数时,你会遇到碰撞问题; 随着时间的推移,其他框架可能需要添加相同的function,并且具有相同名称的本机function甚至可能会出现。 出于这个原因,我只是喜欢使用它来为旧的浏览器添加对现代Web标准的支持,比如在String.prototype中添加'trim'(如果String.prototype.trim本身不存在)。 如果你这样做,确保你的函数的行为与现代标准相同,所以使用它的其他库不会被阻塞。

如果您想添加完全不属于ECMAScript 5等新标准的全新function,通常最好将它们添加到实用程序对象或使其成为普通function。 这不会让他们跑得更快。 它只是让你的代码更容易维护几年后。