JavaScript中:表達(dá)式和語(yǔ)句的區(qū)別[譯]
JavaScript中的表達(dá)式和語(yǔ)句是有區(qū)別的.一個(gè)表達(dá)式會(huì)產(chǎn)生一個(gè)值,它可以放在任何需要一個(gè)值的地方,比如,作為一個(gè)函數(shù)調(diào)用的參數(shù).下面的每行代碼都是一個(gè)表達(dá)式:
myvar3 + xmyfunc("a", "b")語(yǔ)句可以理解成一個(gè)行為.循環(huán)語(yǔ)句和if語(yǔ)句就是典型的語(yǔ)句.一個(gè)程序是由一系列語(yǔ)句組成的.JavaScript中某些需要語(yǔ)句的地方,你可以使用一個(gè)表達(dá)式來(lái)代替.這樣的語(yǔ)句稱之為表達(dá)式語(yǔ)句.但反過(guò)來(lái)不可以:你不能在一個(gè)需要表達(dá)式的地方放一個(gè)語(yǔ)句.比如,一個(gè)if語(yǔ)句不能作為一個(gè)函數(shù)的參數(shù).
2.其他語(yǔ)法
看看下面這兩對(duì)類似的語(yǔ)法,搞懂這些后,能夠幫助我們更好的理解語(yǔ)句和表達(dá)式之間的關(guān)系.
2.1 If語(yǔ)句和條件運(yùn)算符
下面是一個(gè)if語(yǔ)句的例子:
var x;
if (y >= 0) {
x = y;
} else {
x = -y;
}
類似if語(yǔ)句功能的表達(dá)式叫做條件運(yùn)算符.上面的語(yǔ)句等價(jià)于下面的.
var x = (y >= 0 ? y : -y);
在等于號(hào)=和分號(hào);之間的代碼就是條件表達(dá)式.兩邊的小括號(hào)不是必需的,但我覺(jué)得小括號(hào)能讓條件表達(dá)式更易讀.
2.2 分號(hào)和逗號(hào)運(yùn)算符
在JavaScript中,使用分號(hào)可以連接兩個(gè)語(yǔ)句:
foo(); bar()要想連接兩個(gè)表達(dá)式,使用的是不常見(jiàn)的逗號(hào)運(yùn)算符:
foo(), bar()逗號(hào)運(yùn)算符會(huì)計(jì)算前后兩個(gè)表達(dá)式,然后返回右邊表達(dá)式的計(jì)算結(jié)果.例如:
> "a", "b"
'b'
> var x = ("a", "b");
> x
'b'
> console.log(("a", "b"));
3.看似語(yǔ)句的表達(dá)式
一些表達(dá)式看起來(lái)像是語(yǔ)句,這可能會(huì)帶來(lái)一些麻煩.
3.1 對(duì)象字面量和語(yǔ)句塊
下面是一個(gè)對(duì)象字面量,也就是一個(gè)可以生成一個(gè)對(duì)象值的表達(dá)式.
{
foo: bar(3, 5)
}
不過(guò)同時(shí),它也是一個(gè)完全合法的語(yǔ)句,這個(gè)語(yǔ)句的組成部分有:
•一個(gè)代碼塊:一個(gè)由大括號(hào)包圍的語(yǔ)句序列.
•一個(gè)標(biāo)簽:你可以在任何語(yǔ)句前面放置一個(gè)標(biāo)簽.這里的foo就是一個(gè)標(biāo)簽.
•一條語(yǔ)句:表達(dá)式語(yǔ)句bar(3, 5).
你也許會(huì)感到震驚,那就是JavaScript居然可以有獨(dú)立的代碼塊(常見(jiàn)的代碼塊是依托于循環(huán)或者if語(yǔ)句的).下面的代碼演示了這種代碼塊的作用:你可以給它設(shè)置一個(gè)標(biāo)簽然后跳出這個(gè)代碼塊.
function test(printTwo) {
printing: {
console.log("One");
if (!printTwo) break printing;
console.log("Two");
}
console.log("Three");
}
> test(false)
One
Three
> test(true)
One
Two
Three
3.2 函數(shù)表達(dá)式和函數(shù)聲明
下面的代碼是一個(gè)函數(shù)表達(dá)式:
function () { }你還可以給這個(gè)函數(shù)表達(dá)式起一個(gè)名字,將它轉(zhuǎn)變?yōu)橐粋€(gè)命名(非匿名)的函數(shù)表達(dá)式:
function foo() { }這個(gè)函數(shù)的函數(shù)名(foo)只存在于函數(shù)內(nèi)部,比如,可以用它來(lái)做遞歸運(yùn)算:
> var fac = function me(x) { return x <= 1 ? 1 : x * me(x-1) }
> fac(10)
3628800
> console.log(me)
ReferenceError: me is not defined
一個(gè)命名的函數(shù)表達(dá)式從表面上看起來(lái),和一個(gè)函數(shù)聲明并沒(méi)有什么區(qū)別.但他們的效果是不同的:一個(gè)函數(shù)表達(dá)式產(chǎn)生一個(gè)值(一個(gè)函數(shù)).一個(gè)函數(shù)聲明執(zhí)行一個(gè)動(dòng)作:將一個(gè)函數(shù)賦值給一個(gè)變量. 此外,只有函數(shù)表達(dá)式可以被立即調(diào)用,函數(shù)聲明不可以.
3.3 解決沖突
從3.1和3.2可以看出,有些表達(dá)式和語(yǔ)句在表面上看不出有什么區(qū)別.也就意味著,相同的代碼,出現(xiàn)在表達(dá)式上下文和出現(xiàn)在語(yǔ)句上下文會(huì)表現(xiàn)出不同的作用.通常情況下,這兩種上下文是沒(méi)有交集的.但是,如果是表達(dá)式語(yǔ)句的話,會(huì)有一個(gè)重疊:也就是說(shuō),會(huì)有一些表達(dá)式出現(xiàn)在語(yǔ)句上下文上.為了解決這種歧義,JavaScript語(yǔ)法禁止表達(dá)式語(yǔ)句以大括號(hào)或關(guān)鍵字"function"開(kāi)頭:
ExpressionStatement :
[lookahead ∉ {"{", "function"}] Expression ;
那么,如果你想寫一個(gè)以那些標(biāo)志開(kāi)頭的表達(dá)式語(yǔ)句,該怎辦呢? 你可以把它放在一個(gè)括號(hào)內(nèi)部,這樣并不會(huì)改變運(yùn)行結(jié)果,只會(huì)確保該表達(dá)式被解析在表達(dá)式上下文中.讓我們看兩個(gè)例子.第一個(gè)例子:eval會(huì)按照語(yǔ)句上下文解析它的參數(shù).如果你想讓eval返回一個(gè)對(duì)象,你必須在對(duì)象字面量?jī)蛇吋由弦粋€(gè)括號(hào).
> eval("{ foo: 123 }")
123
> eval("({ foo: 123 })")
{ foo: 123 }
第二個(gè)例子:下面的例子是一個(gè)立即執(zhí)行的函數(shù)表達(dá)式.
> (function () { return "abc" }())
'abc'
如果你省略了小括號(hào),你會(huì)得到一個(gè)語(yǔ)法錯(cuò)誤(函數(shù)聲明不可以是匿名的):
> function () { return "abc" }()
SyntaxError: function statement requires a name
如果你添加上函數(shù)名,還會(huì)得到一個(gè)語(yǔ)法錯(cuò)誤(函數(shù)聲明不能被理解執(zhí)行):
> function foo() { return "abc" }()
SyntaxError: syntax error
另外一個(gè)能讓表達(dá)式在表達(dá)式上下文上被解析的辦法是使用一元運(yùn)算符,比如 + 或者 !.但是,和使用括號(hào)不同的是,這些操作符會(huì)改變表達(dá)式的運(yùn)行結(jié)果.如果你不關(guān)心結(jié)果的話,完全可以使用:
> +function () { console.log("hello") }()
hello
NaNNaN
是+作用在函數(shù)執(zhí)行后的返回值undefined上的結(jié)果.
譯者注:我覺(jué)的沒(méi)翻譯明白,所以用拙劣的水平畫了張圖.

原文(英文):http://www.2ality.com/2012/09/expressions-vs-statements.html
- javascript語(yǔ)句中的CDATA標(biāo)簽的意義
- javascript while語(yǔ)句和do while語(yǔ)句的區(qū)別分析
- JavaScript中SQL語(yǔ)句的應(yīng)用實(shí)現(xiàn)
- Javascript技巧之不要用for in語(yǔ)句對(duì)數(shù)組進(jìn)行遍歷
- 關(guān)于JavaScript的with 語(yǔ)句的使用方法
- javascript 循環(huán)語(yǔ)句 while、do-while、for-in、for用法區(qū)別
- javascript中break,continue和return語(yǔ)句用法小結(jié)
- javascript教程:關(guān)于if簡(jiǎn)寫語(yǔ)句優(yōu)化的方法
- JavaScript 學(xué)習(xí)筆記之語(yǔ)句
相關(guān)文章
概述javascript在Google IE中的調(diào)試技巧
本篇文章主要是對(duì)javascript在Google IE中的調(diào)試技巧進(jìn)行了介紹,需要的朋友可以過(guò)來(lái)參考下2016-11-11Axios設(shè)置token請(qǐng)求頭的三種方式
用戶登錄時(shí),后端會(huì)返回一個(gè)token,并且保存到瀏覽器的localstorage中,可以根據(jù)localstorage中的token判斷用戶是否登錄,所以當(dāng)發(fā)送請(qǐng)求時(shí),都要攜帶token給后端進(jìn)行判斷,本文給大家介紹了Axios設(shè)置token請(qǐng)求頭的三種方式,需要的朋友可以參考下2024-02-02ES6知識(shí)點(diǎn)整理之函數(shù)數(shù)組參數(shù)的默認(rèn)值及其解構(gòu)應(yīng)用示例
這篇文章主要介紹了ES6知識(shí)點(diǎn)整理之函數(shù)數(shù)組參數(shù)的默認(rèn)值及其解構(gòu)應(yīng)用,結(jié)合實(shí)例形式分析了ES6函數(shù)數(shù)組參數(shù)解構(gòu)賦值和默認(rèn)值的設(shè)置相關(guān)操作技巧,需要的朋友可以參考下2019-04-04div+css布局的圖片連續(xù)滾動(dòng)js實(shí)現(xiàn)代碼
整理一個(gè)div+css圖片連續(xù)滾動(dòng)代碼,原理跟腳本之家之前發(fā)布的文章一樣。2010-05-05Three.js利用orbit controls插件(軌道控制)控制模型交互動(dòng)作詳解
這篇文章主要給大家介紹了關(guān)于Three.js利用orbit controls插件,也就是軌道控制來(lái)控制模型交互動(dòng)作的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-09-09js實(shí)現(xiàn)鼠標(biāo)懸停圖片上時(shí)滾動(dòng)文字說(shuō)明的方法
這篇文章主要介紹了js實(shí)現(xiàn)鼠標(biāo)懸停圖片上時(shí)滾動(dòng)文字說(shuō)明的方法,涉及js操作鼠標(biāo)事件的使用技巧,需要的朋友可以參考下2015-02-02基于javascript html5實(shí)現(xiàn)多文件上傳
這篇文章主要為大家詳細(xì)介紹了基于javascript html5實(shí)現(xiàn)多文件上傳的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-03-03Sample script that deletes a SQL Server database
Sample script that deletes a SQL Server database...2007-06-06