亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

重讀 Axel 的 Javascript 中的 Expression vs Statement 一文

馬龍駒 / 3041人閱讀

摘要:主要是因為它們會因為不同的位置產(chǎn)生不同的行為。函數(shù)宣告則產(chǎn)生一個行為,即建立一個變數(shù),然後它的值是一個。而且只有可以被立即調(diào)用,函數(shù)宣告不行。為了防止產(chǎn)生疑義。會禁止使用或開頭。屬於一種,其產(chǎn)生一個值或說回傳一個值,並完成某項任務(wù)。

前言

原文在此,對於 Axel 的文章一直有種雖然短卻難以讀透的感覺。這篇文章是再讀一次的筆記與部份翻譯,如有錯誤歡迎指教。

註: 下面一些範(fàn)例當(dāng)我們在瀏覽器 console 執(zhí)行時,回傳值與程式執(zhí)行的順序在 Chrome 與 Firefox 會有差別。注意一下箭頭符號就知道哪個是 return 了。如下範(fàn)例

  > function foo () {console.log("foo");}
  > foo();

  // 在 Chrome 是
  foo
  undefined

  // 在 Firefox 是
  undefined
  foo
1. Statements 述句和 Expressions 表達(dá)式

一直以來,在讀技術(shù)文章的時候您一定不陌生這兩個詞,因為小弟過去對於這種細(xì)枝末節(jié)並不是很重視,加上計算機背景又不深厚。所以對於一些文章和概念的掌握度一直不是很精確。這次重讀一遍 Axel 的文章,希望能夠?qū)?javascript 有更深入的理解。

事實上,在 javascript 中能夠清楚的分辨 expressionsstatements 的差異對於撰寫程式碼是有一定的幫助,可以避免掉入一些陷阱。

簡單來說一個表達(dá)式 expressions 會產(chǎn)生一個值,我們會在撰寫它的地方期望得到一個。舉例來說像是調(diào)用 function 中的引數(shù)(arguments),或者指定式 = 的右邊都屬於 expressions 的位置。

參數(shù)(parameters),引數(shù)(arguments)

parameters 即在 function 中定義必須在呼叫程序時傳遞,可以用來取值的符號(變數(shù)名稱)

arguments 是實際呼叫時,傳入的值

下面的每一行都是一個 expression:

myvar
100 + x
fn("a", "b")

而大體來說述句 statements 即執(zhí)行動作,完成特定任務(wù)。賦值,迴圈和 if 述句都是 statements 的例子。
在我們實際撰寫的程式碼中到底是怎麼區(qū)分的呢?讓我們看看 MDN 上定義的 if 述句

if (condition)
   statement1
[else
   statement2]

要明白這些事情我們得先從 syntax 開始講起,基本上程式是透過一系列規(guī)定好的語法組成,稱為 syntax ,它類似於我們?nèi)祟愓Z言中的文法,不管是中文還是英文。一個程式要遵循著 syntax 並且由一系列 statements 組成的。

javascript 直譯器在解析程式碼時對於語法結(jié)構(gòu),即這些程式碼出現(xiàn)的位置會有對應(yīng)的處理方式。

另外,拿上面的例子來說,任何 javascript 預(yù)期會有 statements 的地方你都可以使用 expressions,例如在 statement1 的地方呼叫一個 function。
這個 function 就稱作 expression statement 屬於一種特殊的 statement ,這個 function 自然可以 return 一個值,同時也可以在內(nèi)部產(chǎn)生一些 side effect,不過如果我們重點擺在一些 side effect 部分時,通常就會回傳 undefined。如下圖

通常一個 statement 是獨立的,只會完成某項任務(wù),不過如果它影響了整個程式例如: 異動了機器內(nèi)部的狀態(tài),或者影響後面的 statement,這些造成的改變我們就稱為 side effect (副作用)

反過來,我們不可以在預(yù)期是 expression 的地方換成 statement。例如我們不可以在 function 的引數(shù)的地方改成 if 述句。

歸納一下關(guān)係如下:

syntax

statements

expression statements

expressions

2. statements 與 expressions 實例

讓我們看一下這兩段類似功能的程式碼,我們可能會更加清楚它們之間的分別。

if 條件式語句和條件運算子(三元運算子)
var x;
if (y >= 0) {
  x = y;
} else {
  x = -y;
}

上面這幾句程式碼無疑都是 statements,另外 expression 也有個對應(yīng)的寫法和上面這段程式碼完全等價

var x = (y >= 0 ? y : -y);

在等號和分號之間的就是一個 expression,其中的 () 不是必須的,但加上去比較容易閱讀。

分號; 與 逗號,

在 javascript 中 statement 之間我們可以用 ; 分號來區(qū)分和串連。

foo(); bar()

expression 也有一個鮮為人知的 , 運算子可以用來串連。

foo(), bar()

兩個 expression 都會執(zhí)行,但是返回最後面的。

> "a", "b"
"b"

> var x = ("x", "y")
> x
"y"
3. 容易產(chǎn)生誤會的 expressions (看起來像 statements)

有些 expressions 看起來像是 statements。下面我們會列出一些容易產(chǎn)生疑義的例子逐一討論。主要是因為它們會因為不同的位置產(chǎn)生不同的行為。

物件實字(Object Literal)與程式碼區(qū)塊(Block)

下面這段範(fàn)例是一個物件實字,屬於 expression ,用來產(chǎn)生一個物件

{
  foo: bar(3, 5)
}

Object Literal 是一個透過 {}, 逗號分隔的鍵值對列表就是 var o = {name:"Object"} 這樣的寫法。

同時它還是一個符合規(guī)範(fàn)的 statement,因為它具備了:

block: 一段 statement 放在 {}

label: 我們可以在任何一段 statement 之前放上一個 label,在這邊 label 是 foo:

statement: 一個 expression statement bar(3, 5)

所以 {} 到底是一個 block 還是物件實字,你可能會說是物件那讓我們來看看下面這個奇怪的例子

// 在看這個奇怪的範(fàn)例之前讓我們先看看一些 javascript 的行為
// 當(dāng)我們把非數(shù)字相加時
> 1 + "string"
"1string"

> 1 + undefined
NaN

> 1 + null
1

> 1 + [2,3,]
"12,3"

> 1 + {name: "andyyou"}
"1[object Object]"

// 上面的範(fàn)例我們得知,除了 undefined 和 null,基本上 js 會把物件先 `toString()` 再相加。

> [].toString()
""

> [1, 2, 3].toString()
"1,2,3"

> var o = {};
> o.toString();
"[object Object]"

// 有了上面的基礎(chǔ)知識之後,讓我們來看看這令人嚇尿的行為

> [] + {}
"[object Object]"

// 好!這題如我們所料,[] 產(chǎn)生 "" 加上 {} 產(chǎn)生 "[object Object]"

// 先問你個問題: + 兩邊的運算元能不能互換而結(jié)果不變
// 你可能回答: 是!??!
// 但....

> {} + []
0

上面程式碼最後一句的 {} 是一個 block 所以執(zhí)行完之後接 +[]。

> +[]
0

嚇尿了吧!除了 if, 迴圈外 javascript 也具有獨立的 block。
下面這段程式碼說明了 labelblock 的用法:

function test (printTwo) {
  printing: {
    console.log("One");
    if (!printTow) break printing;
    console.log("Two");
  }
  console.log("Three");
}

執(zhí)行的結(jié)果

> test(false)
"One"
"Three"

> test(true)
"One"
"Two"
"Three"

從上面驗證了 {} 的語法如果遇到 statements 的位置,就會被當(dāng)成 statements,而如果在 expressions 的位置就會被當(dāng)解析成一個值。

> {} + [];
// 就是一個最好的例子,{} 被當(dāng)作 statement 就是一個 block

// 如果換成

> var x = {};
// 那他就是一個 expression 代表一個值 - 一個物件

讓我們接著看下一個例子。

Function expression 與 function 宣告

下面的程式碼是一個 function expression

function () {}

你也可以給 function expression 一個名稱

function foo () {}

在當(dāng)作 function expression 時上面的 function 名稱 foo 只存在在 function 內(nèi)部能使用,舉例來說像是一個遞迴。
你可能困惑了,我們到底在說啥?看看下面的例子,我們要說的是當(dāng) function 放在 statementsexpressions 不同位置時的差異(放在 = 右邊是 expression)

var fn = function me(x) { return x <= 1 ? 1 : x * me(x-1)} // = 等號右邊是一個 expression 的位置
fn(10); // 3628800

console.log(me); // ReferenceError: me is not defined

具名的 function expression 和函數(shù)宣告的寫法看起來是沒有區(qū)別的。但實際上這兩者的效果截然不同,function expression 產(chǎn)生一個值(一個 function)。函數(shù)宣告則產(chǎn)生一個行為,即建立一個變數(shù),然後它的值是一個 function。而且只有 function expression 可以被立即調(diào)用,函數(shù)宣告不行。

從上面這幾點看來能夠區(qū)分 expression 和 statement 挺重要的。

4. 使用物件實字與 function expression 當(dāng)作 statements

我們已經(jīng)看到有一些 expressionstatement 語法上是沒有區(qū)別的。這意味著相同的程式碼會有不同行為取決於它出現(xiàn)在 expression 的位置
或者是 statement 位置。為了防止產(chǎn)生疑義。javascript 會禁止 expression statement 使用 {}function 開頭。

換句話說就是在 javascript 認(rèn)定為 statement 的位置,使用了 expression 會變成 expression statement。這並不是 expression,所以產(chǎn)生一些特殊的狀況 {} 會被當(dāng)作 block 解釋,function 開頭的語法會被當(dāng)作函數(shù)定義。
所你當(dāng)你想要使用這兩者為開頭撰寫 expression statement 時,你可以放上 () 可以確保位於一個 expression 的位置。

這就是 statement 或者 expression 所延伸的問題,也可以說造成我們極度混亂的根源。讓我們來看看 eval 和立即調(diào)用函式:

eval

eval 會解析他的引數(shù)當(dāng)做一句 statement。如果你希望 eval 回傳一個物件你就需要在物件實字外圍放上()

> eval("{foo: 123}");
123

> eval("({foo: 123})");
{foo: 123}

下次再閱讀文件的時候是不是更有感覺了。

立即調(diào)用函式

立即調(diào)用函式的部分

> (function () { return "abc" }())
"abc"

如果你省略了 () 如下,你就會得到一個語法錯誤的訊息。function 宣告不可以匿名。

> function () { return "abc" }()
SyntaxError: function statement requires a name

就算替 function 加上名稱還是噴錯

> function foo() { return "abc" }()
SyntaxError: syntax error

因為函數(shù)宣告不能立即調(diào)用(IIFE),不過除了使用 () 還有些技巧,當(dāng)我們硬要要把某段程式當(dāng)做 expression 執(zhí)行時,可以使用一元運算子 +!,不過和()的方式比起來這會影響回傳結(jié)果,如果你不在意的話這也是一種方式。

> +function () { console.log("hello") }()
NaN
hello

這個 NaN 是 + 遇上 undefined 的結(jié)果,喔!對了還有一種是透過 void 的方式

> void function () { console.log("hello") }()
undefined
hello
連續(xù)使用立即調(diào)用函式

當(dāng)你在連續(xù)呼叫 IIFE 的時候必須要注意不要忘記分號 ; 結(jié)尾

(function () {}())
(function () {}())
// TypeError: undefined is not a function

上面的程式碼會產(chǎn)生錯誤因為 javascript 以為第二行的 () 是要拿第一行產(chǎn)生的結(jié)果當(dāng)作一個函數(shù)來呼叫。

(function () {}());
(function () {}())
// OK

下面範(fàn)例因為 javascript 自動補上分號的功能,使用一元運算子的話 ; 可以省略。

void function () {}()
void function () {}()
// OK

javascript 會自動補上分號是因為接在第一行之後的 void 並不是可以接下去的語句(符合規(guī)範(fàn)能串在一起的寫法)。

另外關(guān)於 javascript 自動補上分號有幾項建議如下:

在 return,break,continue,++,-- 五種 statement 中,換行字元可完全等於 ;

var,if,do while,for,continue,break,return,with,switch,throw,try,debugger 關(guān)鍵字開頭,以及空的 statement,上一行會自動補上分號。

遇到 expression statement 和 function expression 情況非常複雜,後面請務(wù)必要加上分號。

([ 開頭的 statements 前面或上一句不加非常危險。

想要更深入明白 ASI,請參考。

總結(jié)

syntax : 語法(文法),該怎麼組織 statements 與 expressions。

expressions : 會產(chǎn)生一個值,其意義就是代表一個值的表式例如 x + y

statements : 完成某項任務(wù)的操作。賦值,條件判斷,宣告都算是 statements; if (condiction) { console.log("WoooW!") }。

expression statements : 屬於一種 statement,其產(chǎn)生一個值(或說回傳一個值),並完成某項任務(wù)。例如:x += 1 或者在 statement 執(zhí)行一個 side effect 的函數(shù)呼叫。

在 statements 位置放入 expressions 要小心(即 expression statement),因為 javascript 對於 expressionexpression statement 解釋行為是不一樣的。

下面這兩種語法對於其位置尤其需要注意

function

statement 位置: 當(dāng)作函數(shù)宣告,即建立一個變數(shù)它的值是一個 function。,不能立即調(diào)用。

expression 位置: 為 function expression 產(chǎn)生一個為 function 的值,可以被立即調(diào)用(IIFE)。

{}

statement 位置: block 一個程式碼區(qū)塊,例如 for, label 的 block。

expression 位置: 物件實字,建立一個值 - 物件。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/86283.html

相關(guān)文章

  • 關(guān)於 Javascript {} + {}

    摘要:於是其他的東西相加的時候?qū)晦D(zhuǎn)型成數(shù)字或者字串。整個過程即先依據(jù)轉(zhuǎn)換為原始型別,這裡要注意並不是最終結(jié)果,再來依據(jù)需要看是否要再將原生型別轉(zhuǎn)成數(shù)字或字串。這個結(jié)果等於只作的算。 這篇文章源自 What is {} + {} in JavaScript? 其實早在 2012 年就問世了。時至 2016 年末純粹是在聊天時重提這個問題,但由於年紀(jì)大了記憶力不佳,竟然記錯了,所以才會有這一...

    charles_paul 評論0 收藏0
  • JavaScript 闖關(guān)記》之語句

    摘要:會自動調(diào)用轉(zhuǎn)換函數(shù)將這個表達(dá)式的結(jié)果轉(zhuǎn)換為一個布爾值。語句語句與語句的關(guān)系最為密切,而且也是在其他語言中普遍使用的一種流控制語句。 表達(dá)式在 JavaScript 中是短語,那么語句就是整句命令。表達(dá)式用來計算出一個值,語句用來執(zhí)行以使某件事發(fā)生。從本質(zhì)上看,語句定義了 JavaScript 中的主要語法,語句通常使用一或多個關(guān)鍵字來完成給定任務(wù)。語句可以很簡單,例如通知函數(shù)退出;也可...

    OBKoro1 評論0 收藏0
  • JS基礎(chǔ)學(xué)習(xí)04「語句」

    摘要:表達(dá)式用來計算出一個值,語句用來執(zhí)行以使某件事發(fā)生。其中,語句會立即退出循環(huán),強制繼續(xù)執(zhí)行循環(huán)后面的語句。在執(zhí)行語句之后,結(jié)果顯示。語句語句的作用是指定函數(shù)調(diào)用后的返回值。語句語句的作用是把程序運行時產(chǎn)生的錯誤顯式地拋出異常。 表達(dá)式在 JavaScript 中是短語,那么語句就是整句命令。表達(dá)式用來計算出一個值,語句用來執(zhí)行以使某件事發(fā)生。從本質(zhì)上看,語句定義了 JavaScript...

    remcarpediem 評論0 收藏0
  • 【知識點】Javascript分號規(guī)則

    摘要:花點時間搞清楚中的分號規(guī)則吧不管你喜歡結(jié)尾帶分號或省略分號的模式分號允許的場景分號一般允許出現(xiàn)在大部分語句的末尾,比如等栗子僅有一個分號可以表示空語句在中合法,比如可解析為三個空語句空語句可用于輔助產(chǎn)生語法合法的解析結(jié)果,如如果沒有末尾的 花點時間搞清楚JS中的分號規(guī)則吧~~~不管你喜歡結(jié)尾帶分號或省略分號的模式 分號允許的場景 分號一般允許出現(xiàn)在大部分語句(statement)的末尾...

    kun_jian 評論0 收藏0
  • 一文快速解讀ES6新特性

    摘要:是一項標(biāo)準(zhǔn),于年月獲得批準(zhǔn)。靜態(tài)限制在分配之前阻止使用。使用通用到基于自定義迭代器的迭代。迭代基于這些鴨子類型接口僅使用類型語法進(jìn)行展示生成器生成器使用和簡化迭代器。生成器是迭代器的子類型,包括額外的和。 ECMAScript 2015是一項ECMAScript標(biāo)準(zhǔn),于2015年6月獲得批準(zhǔn)。 ES2015是該語言的重要更新,也是自2009年ES5標(biāo)準(zhǔn)化以來該語言的第一次重大更新?,F(xiàn)在...

    goji 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<