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

时间:2011-06-27 17:32:56

标签: javascript jquery performance node.js

在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;
    }
}

5 个答案:

答案 0 :(得分:12)

在性能方面,效果为零。

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

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

答案 1 :(得分:7)

首先关闭原型比对象上的函数慢。创建一个函数有一个成本和查找。在原型上查找比仅使用普通对象更昂贵

查看此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>

object method v prototype

话虽如此,在字符串原型上添加内容与将其添加到任何其他原型没有什么不同。

答案 2 :(得分:4)

没有性能损失。它不直接影响任何String对象,该函数仅绑定到String.prototype - 对象。

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

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

答案 3 :(得分:3)

我建议编写自己的原生对象原型扩展库,这比这句话的第一个短语可能建议的更简单快捷。 Prototype.js做了类似的事情,就像我在我维护的各种系统上使用的专有库中一样。此路由的一个优点是库房间兼容性,另一个优点是在不需要扩展方法时减少创建新本机对象的开销。像这样的一些库使用单个对象来扩展方法,我更喜欢有与特定本机对象相关的对象。

(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。

答案 4 :(得分:1)

在性能方面,向String原型添加方法与向任何其他对象添加方法没有什么不同。我还运行了一些测试并且在那里有自定义方法似乎没有减慢任何本地String方法的执行速度 - 即,将'someOtherFunc'添加到String.prototype并不会导致'indexOf'运行得更慢。

当然,你的JavaScript函数会比那些本机版本慢,所以如果你向旧浏览器添加一个“trim”函数,那些具有原生修剪函数的函数将比没有它的那些运行快许多倍。不言而喻。

正如其他人所指出的,当您向核心JavaScript对象的原型添加太多函数时,可能会遇到碰撞问题;随着时间的推移,其他框架可能希望添加相同的功能,甚至可能会出现具有相同名称的本机功能。出于这个原因,我只想使用它来为旧浏览器添加对现代Web标准的支持,例如,如果String.prototype.trim本身不存在,则将“trim”添加到String.prototype。如果你这样做,请确保你的函数的行为与现代标准完全相同,因此使用它的其他库不会被阻塞。

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