Javascript 正在使用缓存的;这";快于;这";当访问同一对象的方法时?
如果我从另一个方法多次访问this.something,缓存“this”并访问something()会更快吗?还是应该反复使用this.something()Javascript 正在使用缓存的;这";快于;这";当访问同一对象的方法时?,javascript,performance,Javascript,Performance,如果我从另一个方法多次访问this.something,缓存“this”并访问something()会更快吗?还是应该反复使用this.something() <script type="text/javascript"> var Foo = (function() { return { something: function() { // Do something }, stuff: function(
<script type="text/javascript">
var Foo = (function() {
return {
something: function() {
// Do something
},
stuff: function(obj) {
this.something(obj);
// ...
this.something(obj);
/* OR should I cache this? */
var $that = this;
$that.something(obj);
// ...
$that.something(obj);
}
};
}());
</script>
var Foo=(函数(){
返回{
某物:函数(){
//做点什么
},
材料:功能(obj){
这是什么(obj);
// ...
这是什么(obj);
/*或者我应该缓存这个*/
var$that=这个;
$that.something(obj);
// ...
$that.something(obj);
}
};
}());
您只需指向对象引用的副本,而不是直接指向对象引用。我无法想象缓存的速度会有多快——但是,嘿,启动一个测试框架,在循环中执行10000次,看看它是否有什么不同。这里只有评测可以回答。但是在进行这种微优化之前,问问自己是否真的需要。我不明白为什么变量应该比this
更快
有些可能更快但我发现不起作用的方法是缓存整个方法查找。。。e、 g.通过执行m=object.method。。。m(x,y,z)代码>。例如,这在Python中是可行的(因为绑定方法的概念),但在Javascript中是不可用的
在javascript中查找方法的结果或多或少地给你一些类似C++的方法指针的东西,换句话说,一个不知道代码>这个< <代码>的函数,因此你必须提供<代码>这个< /代码>你自己可以调用它。
<> >唯一的区别是,在C++中,没有声明静态的任何方法都不能被调用,而不提供<代码> < <代码>,而在JavaScript保存中,方法查找显然只适用于在运行时不需要代码> > 按预期执行的方法。
例如var mycos=Math.cos;霉菌(0.3)至少显然是有效的,因为cos
不需要访问数学(毕竟这并不奇怪)
您可以得到一个在功能上作为缓存方法工作的闭包
var cachedfoo = obj.foo;
var foo = function(x, y, z) { return cachedfoo.call(obj, x, y, z); }
...
foo(1,2,3); // this is the same as obj.foo(1,2,3)
出于其他原因,这可能是有用的,但在我看来,它不会更快(实际上可能会更慢).更新:查看下面CMS的评论,了解真实情况(但我认为它不会改变任何性能)
近似真理:
不,没什么区别。在执行函数时,将创建一个激活对象,并将其放在函数范围链的开头(更具体地说,是其执行上下文)
激活对象具有属性this
,arguments
,每个传递的参数和函数中声明的每个变量都有一个属性
因此,这个
和$那个
生活在同一个范围内,你从中什么也得不到。只有在本地引用范围更大的对象/值时,才能得到改进
+-------------------+ +-------------+
| Execution Context | +->| Scope Chain |
| ----------------- | | | ----------- |
| Scope chain +----+--+ | 0 | +---+----------+
+-------------------+ | 1 | +---+-... |
+-------------+ |
|
|
|
+--------------------+ |
| Activation Object |<--+
| ------------------ |
| this | foo | (if called with foo.method())
| arguments|[someObj]|
| obj | someObj |
| $that | foo | (undefined until assignment)
+--------------------+
+-------------++-------------+
|执行上下文|+->|范围链|
| ----------------- | | | ----------- |
|范围链+-----++|0|+---+----------+
+-------------------+ | 1 | +---+-... |
+-------------+ |
|
|
|
+--------------------+ |
|激活对象|基准测试是确定性能影响的唯一有效方法,是的。但在这种情况下,我敢打赌这不会有任何(明显的)区别。(我对这种方法有一个不同的问题:即使它“快25%”,也不会对99.99%的代码产生任何明显的影响)。我愿意用我的薪水打赌这不会产生任何影响。我还应该指定多次运行…您可以缓存该方法,但您需要使用.call()
或.apply()
为该方法设置this
的正确值(假设您正在调用的方法中使用了this
),而不必指定“this”正是绑定方法的概念。避免方法的查找,但添加“call”的查找并没有那么有趣(call和apply可能是出于与速度不同的原因)。类似于foo=function(x,y,z){return cachedfoo.call(object,x,y,z);}
对于速度IMO:-)来说不会是一个很大的胜利,这是一个很好的观点。它只是将一个属性查找替换为另一个属性查找。主要的一点是,您可以引用一个函数并调用它。要在回答中使用示例,m=object.method。。。m(x,y,z)代码>将起作用。唯一的区别是,如果调用的方法依赖于this
,则需要执行m=object.method。。。m、 调用(这个,x,y,z)代码>:o)我并不想对我的评论感到乏味,但我想你的更新速度会慢一些。每次调用foo
时,您都在创建两个执行上下文,仍然在执行.call()
的属性查找,并且还必须按照作用域链查找obj
。这是因为每次调用foo
时都会计算cachedfoo.call(obj,x,y,z)
,而不是在将函数分配给foo
时计算一次。ES5有一个.bind()
方法,可以消除很多这种情况。总的来说,您的观点是绝对正确的,即缓存此
不会提高性能+1看着你,对图表充满幻想;o) +1太好了!我能借一下吗