2017-08-17 139 views
2

我有以下代碼片段。 我不明白爲什麼最後的sayHello函數運行,相反,我會將ReferenceError作爲sayHello,它在括號範圍內聲明。爲什麼我在調用bloxk範圍外的函數時沒有得到ReferenceError?

{ 
 
\t sayHello(); \t \t \t \t \t // works! 
 

 
\t function sayHello() { 
 
\t \t console.log('Hellow world!'); 
 
\t } 
 
} 
 

 
sayHello(); \t // why it is not // ReferenceError

+1

括號不限制'功能'範圍。 – deceze

+1

@deceze這不完全正確。 – loganfsmyth

回答

4

你打JavaScript語言的一個不幸的向後兼容性邊緣的情況下。

該語言的ES2015(ES6)規範是第一個像您一樣在塊{ ... }內添加功能支持的人。不幸的是,該語言的大多數實現都支持它們,因爲它在技術上被允許作爲該語言的擴展。

要允許依賴此擴展行爲的舊代碼,該語言的較新版本包括Annex B,並且在此情況下特別是B.3.3 Block-Level Function Declarations Web Legacy Compatibility Semantics,它定義了您所看到的行爲。

注意附件中的頭:當主機的ECMAScript是一個Web瀏覽器需要

ECMAScript語言的語法和本附件中規定的語義。如果ECMAScript主機不是網絡瀏覽器,本附件的內容是規範性的,但是是可選的。

這意味着實施此行爲是可選絕對不是你應該依賴的東西。

對於Annex B可選功能,永遠不必抱歉的最簡單方法是始終以嚴格模式運行您的代碼。一般而言,我會說這無論如何都是正確的。

如果您不熟悉,"use strict";就是所謂的「指令」,您可以將它包含在您的JS文件的頂部或單個函數的頂部。在這種情況下,做

"use strict"; 

{ 
    sayHello(); 

    function sayHello() { 
    console.log('Hellow world!'); 
    } 
} 

sayHello(); 

會拋出你期望看到的錯誤。

向前邁進,JavaScript import/export模塊語法也是自動嚴格的,所以從長遠來看,絕大多數代碼將嚴格無論如何都不會遇到這個問題。

相關問題