1

在 JavaScript 中,假设我想从 bObj 内部调用 aObj.myMethod()。在我的应用程序中,从设计的角度来看,aObj 是 bObj 的基类。JavaScript 是一种后期绑定语言,这意味着 myMethod 应该在运行时解析。函数解析是否更快

////////// 如果

1-我很自然地使用我的设计并说 bObj.prototype=aObj 然后在运行时我调用 bObj.myMethod:

function bObj(){...};

bObj.prototype=aObj;


//later
var myBObj=new bObj();
myBObj.myMethod();

////////////////////////或者

2- 通过原型的函数解析可能很慢,所以我将 aObj 作为属性保留在 bObj 中,并从 bObj 内部调用 aObj.myMethod()

function bObj()
{
  this.myAObj=new aObj();
  ...
}     

//later:
var myBObj=new bObj();
myBObj.myAObj.myMethod();

我主要关心的是执行速度。在我的应用程序中,myMethod 每秒被调用数百万次。我知道大多数浏览器都会缓存指向最近调用的函数的指针,因此在这两种情况下,函数解析过程都会加快速度。然而,任何人都可以提供有关这两种情况下函数解析机制的更多细节,并提供一些见解,即哪种方法可能更快?解析机制在所有浏览器中都相同还是完全依赖于浏览器?

4

2 回答 2

1

就您引用的方式而言,您是对的,“函数解析可能很慢”。那么让我们来看看..

在 proto chaing 查找之后,如果您将 myMethod 设为原型方法,例如:aObj.prototype.myMethod=somemethod,那么第一种方法 myBObj.myMethod() 将在第二次尝试时获得“分辨率命中”由于未设置 myBObj 实例 myMethod ,因此继承了原型方法。

第二种方法,myBObj.myAObj.myMethod(),在第二次尝试时会在遇到原型方法时获得“分辨率命中”,因为实例方法未设置(myAObj=new aObj() 未设置 myAObj .myMethod 将设置 myAObj.prototype.myMethod,所以你这样做的方式没有区别。

要从您执行此操作的任何一种方式中获得性能提升,请确保设置您要调用的实例方法,然后引用它:

bObj.myMethod=bObj.prototype.myMethod;
bObj.myMethod();

或者

myAObj.myMethod=myAObj.prototype.myMethod;
bObj.myMethod();

在这两种情况下,第一次查找都会获取实例方法并使用它更好。

要获得最佳性能增益,请完全消除查找并参考原型方法:

myBobj.prototype.myMethod();

或者

myBObj.myAObj.prototype.myMethod();

在最后两种情况下,不需要“功能解析”。

尽管我们都知道 Function 函数在每次使用时都会被解释,并且声明的函数会编译(解释)一次,因此速度更快,但如果将声明的函数设置为对象的原型实际上使其执行更快,这仍然是一个谜。

如果你能找到这一点,那么你就会确切地知道如何获得一个函数,任何函数,以最快的速度执行:声明它或将它设置为原型函数,以最好的为准,如果原型方法更快,通过直接引用原型方法来避免任何原型链查找。

于 2012-01-06T22:57:02.203 回答
0

我刚刚完成了针对这个特定案例的几个性能测试。它在优化模式下与 Mozilla Rhino 1.7R3 一起运行。

您的问题实际上是关于属性查找的。一旦在可用范围链中找到属性(在您的情况下,具有函数值),进一步的操作在两种情况下执行相同。

明显的结果是查找原型上定义的函数的速度较慢。平均而言,调用原型函数需要多花 35% 的时间。直接调用本地函数与直接调用全局范围内的函数我得到了相同的结果。

自己的属性解析得更快,因为它们的范围在原型之前。

做出你的决定。请记住,原型非常适合代码维护和对象重用。

于 2012-01-18T03:22:26.350 回答