2017-07-17 52 views
8

我正在閱讀John Resig編寫的名爲「JavaScript忍者的祕密」的精彩書籍& Bear Bibeaoult。在第3.2章中,它舉了一個例子。爲什麼JavaScript中的匿名函數有名字?

var canFly = function(){ return true; }; 

然後它說:

創建匿名函數並將其分配給名爲canFly的全局變量。由於JavaScript的功能性,函數可以通過該引用作爲canFly()來調用。在這方面,它幾乎在功能上等同於聲明名爲「canFly」的命名函數,但不完全相同。 一個主要區別是函數的名稱屬性是「」,而不是「canFly」。

但是,當我嘗試執行對Chrome的開發者工具的例子,檢查canFly功能的name屬性,它返回值「canFly」,而不是一個空字符串。

canFly.name; 
// > "canFly" 

分配給變量的匿名函數在前幾天沒有名稱嗎?如果是這樣,有什麼變化?還是作者犯了一個錯誤?

+1

我不記得我在哪裏讀過它,但我記得在新版本的Node/V8中,即使匿名函數被分配給一個變量時,也會得到變量名。當我找到一個鏈接時會發佈一個答案。 – Aron

+9

[*推斷的函數名稱*:變量和方法可以從其語法位置推斷匿名函數的名稱(ECMAScript 2015中新增)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Inferred_function_names) –

+1

我們走了。謝謝@亞歷克斯。 – Aron

回答

2

理論上匿名函數是匿名的,意思是無名的。這是它最初實施的方式,十多年來,每個人都對此感到滿意。

然後發生了兩件事:整個Web2.0/ajax運動,人們開始實現在網頁和node.js的桌面應用程序中常見的UI功能。這兩者相結合迫使越來越多的開發人員將JavaScript視爲嚴肅的語言,一旦人們對JavaScript感到滿意,他們開始編寫真正的大型代碼庫。

這導致了有關javascript的可調試性的投訴。有許多從沒有任何有用的調試器(這導致我們真正的瀏覽器是在我看來,退而求其次才MS Visual Studio的好調試器)不知道什麼功能一的console.log來自(因爲他們是匿名) 。

這導致了瀏覽器和JS引擎開發人員能夠實現,試圖猜測的匿名函數「名」的代碼。

理論上這個功能是錯誤的,因爲你不能總是保證你猜測的名稱是函數是如何被調用(例如,如果該功能被分配到幾個不同的變量)。在實踐中,90%的時間工作的東西總比沒有東西好。

+1

有趣的是John Resig的書在2008年出版,因此給我們提供了一個在2008年到2017年之間的粗略時間表,因爲這個功能首次被實現。我相信如果你真的好奇,你可以挖掘各種js引擎的代碼提交的源代碼。蘋果的javascriptcore(硝基),谷歌的v8和微軟的chakracore都是開源的。 – slebetman

+0

非常感謝!看起來我需要學習C/C++來理解瀏覽器引擎的源代碼,但是,我認爲,必須更深入地理解我的問題的答案以及JS實際如何在場景後面工作。 –

1

這裏是你的測試代碼稍微扭捏版本,給出了一個線索,.name可能只是想真的很難有所幫助:

var canFly = function() {}; 
 
var areYouSure = function yesIAm(){}; 
 
console.log(canFly.name); 
 
console.log(areYouSure.name); 
 
console.log((function(){}).name);

檢查細節在MDN我們可以看到它曾經是一個非標準的屬性:

function.name屬性返回函數的名稱。

...這使得它的方式進入ES2015(重點煤礦):

變量和方法可以推斷從句法位置(在ECMAScript中2015年新)一個匿名函數的名稱。

因此,它返回名稱,但如果它不能,它會嘗試猜測。

+0

謝謝!這意味着匿名函數只有在未分配給變量時才具有空的「name」屬性。 –