2013-12-09 24 views
2
var completeObj = {a: { b: { c: { d: { e: { f: 23 } } } } } }; 
var funcA = function(obj){ 
    var a = 'a',b='b',c='c',d='d',e='e',f='f'; 
    return obj[a][b][c][d][e][f]; 
} 

var funcB = function(obj){ 
    return obj['a']['b']['c']['d']['e']['f']; 
} 

FuncA的比funcB慢得多,尋找範圍varible花費這麼多的時間? 測試網址:http://jsperf.com/static-and-dynamic-argument THX爲什麼JavaScript中的變量要慢得多?

+3

因爲代碼做得更多?編譯器不是巧妙的,以實現實現來檢查這些變量是常量,並可以內聯。 – Bergi

回答

2

http://jsperf.com/static-and-dynamic-argument/2

我把你的測試用例,並添加一個給它「證明這一點。」當您通過['key']表示法訪問某個對象中的某些內容時,您的操作與通過.key訪問該對象時的做法相同。編譯器足夠聰明,知道['a']相當於.a。然而,當你在那裏粘貼一個變量時,就像Bergi在他的評論中提到的那樣,編譯器不知道[a]實際上是['a']

1

這是因爲局部變量(函數作用域)成爲內部Variable對象的屬性。因此,要obj[a][b][c][d][e][f]呼叫結束第一然後Variable對象上訪問屬性a通過fcompleteObj

+0

我想知道訪問屬性花費那麼多時間,或者編譯器對內聯對象有一些優化嗎? – Henry

1

它無關變量或變量的作用域(純局部變量實際上是免費的),但使用反射來訪問屬性而不是常量。

obj['a']['b']['c']['d']['e']['f'];

等於obj.a.b.c.d.e.f因此它甚至從源代碼哪些屬性將被訪問已知的。

但是,使用括號表示法與變量,需要在運行時是什麼屬性將訪問搞清楚,所以它是完全不同的。在Java中,前者的代碼就像使用反射庫來訪問屬性,而後者與使用普通的靜態點訪問相同。


那麼爲什麼編譯器沒有意識到變量是靜態的呢?那麼你的代碼是完全不合理的,JIT浪費時間優化不合理的代碼是一個不好的JIT。

爲什麼會意識到['a']是相同.a關係嗎?至少在我的經驗中,解析器爲點和括號訪問吐出相同的MemberAccess對象並檢查表達式是否爲常量字符串要簡單得多。

相關問題