我们应该尽可能共享函数或创建新函数吗?

时间:2011-05-27 07:04:30

标签: javascript web-services

我想知道哪种情况有更多“开销”:

1)案例1:共享30个功能的500万个对象。每次调用函数时都会产生开销,因为需要执行 f.call(instance,arg1,arg2等)

 //example code
function makeObject()
{
  return { method1:func1,
           method2:func2,
           ...
           method30:func30 };
}

2)案例2:500万个对象,每个对象有30个函数(= 1.5亿个单独的函数实例)。每次调用函数时,都没有“路由开销”,但当然牺牲了更多实例

//example code
function makeObject()
{
  return { method1:func1.bind(asd),
           method2:func2.bind(asd),
           ...
           method30:func30.bind(asd) };
}

500万只是我手指输入的一个数字,而我的大脑仍在为一个例子找出一个不错的数字。

基本上我想知道我们应该尽可能分享功能还是创建新功能?

(你可以假设我永远不会在整个页面的任何地方使用eval函数)

3 个答案:

答案 0 :(得分:5)

由于几乎所有现代浏览器都会优化prototype-scopeschain查找,因此您绝对应该分享方法。

用简单的单词描述的优化技术是一种hash lookup table,javascript引擎用来从out of scope变量访问属性/方法。因此,与经典scope chain lookup进行比较的开销非常小,其中引擎必须遍历每个父范围变量/激活对象。

如果存在某种直接lookup'ed代码,则此优化eval只会失败。由于eval可以从上下文中更改属性,因此引擎必须回退到经典的查找算法(这有点慢)。

然而,对于Javascript引擎来说,500万个对象是不真实的,我希望这些数字只是一些例子。在现实世界中,调用n个函数的5m对象会在周围创建堆栈溢出和“运行时间过长”错误。

单独parsing time的1.5亿个功能将是不光彩的。

答案 1 :(得分:1)

如果假设案例2是关于创建类似于此的对象:

function makeObject()
{
  return { method1:func1,
           method2:func2,
           ...
           method30:func30 };
}

然后你将拥有5米长的30个属性的对象。不是“1.5亿个人功能实例”。函数实例数仍为30。

要创建5米这样的对象会花费你一些东西。添加属性比阅读它要贵3到10倍。这意味着创建此类集可能比使用__proto__使用一级间接寻址访问方法花费的时间更多。

简而言之:对于5m / 30,情况1在大多数情况下更为理想。但有些情况下,将方法引用放入对象本身是值得考虑的。例如。经常访问的对象/方法的数量有限(例如单身)。

答案 2 :(得分:1)

为什么不这样呢? :

function myObject() { }

myObject.prototype.method1 = func1
myObject.prototype.method2 = func2,
           ...
myObject.prototype.method30 = func30

因此,如果您将对象创建为

var obj = new myObject();

然后你将其方法称为:

obj.method1(); 
obj.method2(); 

不需要call()和其他魔法......

在这种情况下,您不需要使用相同的30个属性填充对象的每个实例。