你不知道的 JavaScript 系列中( 31 ) - 讓人誤解的語句
阿新 • • 發佈:2020-11-30
語句的結果值
下面這樣的程式碼無法執行:
上下文規則
{}
var a = 3 * 6; var b = a; b;以賦值表示式 b = a 為例,其結果值是賦給 b 的值(18),但規範定義 var 的結果值是 undefined。如果在控制檯中輸入var a = 42會得到結果值 undefined,而非 42 如果你用開發控制檯除錯過程式碼,應該會看到很多語句的返回值顯示為 undefined,只是你可能從未探究過其中的原因。 其實控制檯中顯示的就是語句的結果值
var b; if (true) { b = 4 + 38; }
在控制檯中輸入以上程式碼應該會顯示 42,即最後一個語句 / 表示式 b= 4 + 38 的結果值。 換句話說,程式碼塊的結果值就如同一個隱式的返回,即返回最後一個語句的結果值。
var a, b; a = if (true) { b = 4 + 38; };
因為語法不允許我們獲得語句的結果值並將其賦值給另一個變數(至少目前不行)
var a = 2; var b = a + 3;表示式 a + 3 本身沒有副作用(比如改變a的值)。它的結果值為5,通過 b = a + 3 賦值 給變數 b。
var a = 42; var b = a++;
a++ 首先返回變數 a 的當前值 42(再將該值賦給 b),然後將 a 的值加 1:
var a = 42;
var b = a++; a;// 43 b; // 42
很多開發人員誤以為變數 b 和 a 的值都是 43,這是因為沒有完全理解 ++ 運算子的副作用 何時產生。
var a = 42; a++; // 42 a; // 43 ++a; // 44 a; // 44++ 在前面時,如 ++a,它的副作用(將 a 遞增)產生在表示式返回結果值之前,而 a++ 的 副作用則產生在之後 但也不是沒有辦法,可以使用,語句系列逗號運算子(statement-series comma operator)將 多個獨立的表示式語句串聯成一個語句:
var a = 42, b; b = ( a++, a ); a; // 43 b; // 43a++, a中第二個表示式a在a++之後執行,結果為43,並被賦值給b。
// 假定函式bar()已經定義 var a = { foo: bar() };
{ .. }被賦值給a,因而它是一個物件常量。
{
foo: bar()
}
{ .. } 在這裡只是一個普通的程式碼塊。JavaScript 中這種情況並不多見(在其他語言中則常見得多),但語法上是完全合法的,特別是和 let(塊作用域宣告)在一起時非常有用
還有一個坑常被提到(涉及強制型別轉換,參見第 4 章):[] + {}; // "[object Object]" {} + []; // 0第一行程式碼中,{} 出現在 + 運算子表示式中,因此它被當作一個值(空物件)來處理。[]會被強制型別轉換為"",而{}會被強制型別轉換為"[object Object]"。 但在第二行程式碼中,{} 被當作一個獨立的空程式碼塊(不執行任何操作)。程式碼塊結尾不需 要分號,所以這裡不存在語法上的問題。最後+ []將[]顯式強制型別轉換(參見第4章) 為0。
else if 和可選程式碼塊
if (a) { // .. }else if (b) { // .. }else { // .. }
事實上 JavaScript 沒有 else if,但 if 和 else 只包含單條語句的時候可以省略程式碼塊的 { }。下面的程式碼你一定不會陌生:
if (a) doSomething( a );
很多JavaScript程式碼檢查工具建議對單條語句也應該加上{ },如:
if (a) { doSomething( a ); }
else也是如此,所以我們經常用到的else if實際上是這樣的:
if (a) { // .. }else { if (b) { // .. }else { // .. } }
if (b) { .. } else { .. }實際上是跟在else後面的一個單獨的語句,所以帶不帶{ }都可以。換句話說,else if不符合前面介紹的編碼規範,else中是一個單獨的if語句。 else if 極為常見,能省掉一層程式碼縮排,所以很受青睞。但這只是我們自己發明的用法,切勿想當然地認為這些都屬於 JavaScript 語法的範疇。