2017-07-04 46 views
0

我在玩一些EcmaScript 2015的功能,我必須說規範很難理解。javascript中默認函數參數的範圍

我完全理解這個代碼應該拋出某種錯誤:

(function(a = b, b = 1) { })(); 

而且我知道,默認值可以使用外部範圍:

(function() { 
    let c = 1; 
    return (function(a = c) { return a === 1; })(); 
})(); 

但我不明白爲什麼這些示例不好:

(function() { 
    let a = 1; 
    (function(a = a) { })(); 
})(); 

(function() { 
    let b = 1; 
    (function(a = b, b = 2) { })(); 
})(); 

我的Chrome 59.0.3071.115引發ReferenceError t帽子變量沒有定義。

看來Chrome正在進行一些優化,其中只有1個範圍被創建,其中所有參數設置爲不可訪問,並且在分配後將它們逐個添加。

這方面的一些證據可以是:

(function(a =() => b, b = 2) { return a() === 2; })(); 

這看起來像我的口味的失蹤機會,我想知道做規範力在這裏只使用1範圍或這僅僅是V8的實施細則。

難道有人請指點我可以澄清這一點的規範嗎?

+0

'缺少機會,讓我taste' - 這是與其他人的語言文字的問題:對 –

+0

參數範圍是它自己的範圍。在函數聲明表達式中,定義爲參數的符號立即佔優勢。所以'(a = a)'沒有意義,因爲左邊的'a'隱藏了'a'在包含的上下文中。 – Pointy

回答

3

我不明白爲什麼?因爲默認initialisers沒有父範圍進行評估,而是裏面的功能範圍,這些例子並不好

。參數本身已經在範圍上,這樣就可以做這樣的事情

(function(a = 2, b = a) { console.log(b); }()); 

可能有人請點我在規範的地方可能澄清這?

相關欄目爲§9.2.12 FunctionDeclarationInstantiation

我必須說規範很難理解。

是的,儘管它是爲引擎實現者編寫的,而不是程序員。但是,解釋性說明基本上證實了您對優化的理解

如果函數的形式參數不包含任何默認值初始值設定項,則主體聲明將在與參數相同的環境記錄中實例化。如果存在默認值參數初始化程序,則爲正文聲明創建第二個環境記錄。

你的例子基本上desugar到

(function() { 
    let a = arguments[0] !== undefined ? arguments[0] : b, 
//             ^clearly a ReferenceError 
     b = arguments[1] !== undefined ? arguments[1] : 1; 
    { 
    } 
})(); 

(function() { 
    let c = 1; 
    return (function() { 
    let a = arguments[0] !== undefined ? arguments[0] : c; 
//             ^works as you'd think 
    { 
     return a === 1; 
    } 
    })(); 
})(); 

(function() { 
    let a = 1; 
    (function() { 
    let a = arguments[0] !== undefined ? arguments[0] : a; 
//             ^again clearly a ReferenceError 
    { 
    } 
    })(); 
})(); 

(function() { 
    let b = 1; 
    (function() { 
    let a = arguments[0] !== undefined ? arguments[0] : b, 
//             ^still a ReferenceError 
     b = arguments[1] !== undefined ? arguments[1] : 2; 
    { 
    } 
    })(); 
})(); 

(function() { 
    let a = arguments[0] !== undefined ? arguments[0] :() => b, 
//              ^works indeed 
     b = arguments[1] !== undefined ? arguments[1] : 2; 
    { 
    return a() === 2; 
    } 
})(); 
+0

所以它看起來像一個案件是不可行的任何方式。如果每個默認值都在自己的範圍內進行評估,則情況a = b可能是可行的。但是這對於發動機來說會造成太多的開銷,所以電路板只有1個範圍適用於所有參數。看起來這裏的規格很明顯。謝謝。 –