雖然文章標(biāo)題是『語(yǔ)句與表達(dá)式』,在這篇文章中,我將陳述一個(gè)觀(guān)點(diǎn)?每個(gè)表達(dá)式都有一個(gè)值。 在此之外,也會(huì)繼續(xù)表述這個(gè)『代碼之謎』系列的主題——數(shù)學(xué)與計(jì)算機(jī)之間被經(jīng)常忽略的矛盾。
簡(jiǎn)單的講
使用表達(dá)式也是函數(shù)式編程語(yǔ)言所提倡的,而傳統(tǒng)命令式編程語(yǔ)言都是語(yǔ)句的堆砌。
表達(dá)式和語(yǔ)句如何區(qū)分呢? 最簡(jiǎn)單最直觀(guān)的鑒別方法就是,?后面有分號(hào)的是語(yǔ)句, 這是一個(gè)充分條件而不是必要條件。 有分號(hào),就是語(yǔ)句;沒(méi)有分號(hào),就不一定了,也可能是語(yǔ)句,也可能是表達(dá)式。
在動(dòng)態(tài)語(yǔ)言——比如javascript——中是通過(guò)上下文來(lái)區(qū)分這兩者的。
假如如果?function foo(){}
?在一個(gè)賦值表達(dá)式的一部分,則認(rèn)為它是一個(gè)表達(dá)式。?表達(dá)式的一部分,也是表達(dá)式。 而如果?function foo(){}
?被包含在一個(gè)函數(shù)體內(nèi),或者位于程序中,則將它作為一個(gè)語(yǔ)句。
function foo(){}; // 聲明,因?yàn)樗浅绦虻囊徊糠?var bar = function foo(){}; // 表達(dá)式,因?yàn)樗琴x值表達(dá)式的一部分
new function bar(){}; // 表達(dá)式,因?yàn)樗荖ew表達(dá)式的一部分
(function(){
function bar(){}; // 聲明,因?yàn)樗呛瘮?shù)體的一部分
})();
還有一種不那么顯而易見(jiàn)的表達(dá)式,就是被包含在一對(duì)圓括號(hào)中——?(function foo(){})
。 將這種形式看成表達(dá)式同樣是因?yàn)樯舷挛牡年P(guān)系: (和)構(gòu)成一個(gè)分組操作符,而?分組操作符只能包含表達(dá)式:
(function foo(){}); // 函數(shù)表達(dá)式:注意它被包含在分組操作符中
(var x = 5); // error! 分組操作符只能包含表達(dá)式,不能包含語(yǔ)句(這里的var就是語(yǔ)句)
今天突然有人問(wèn)我:
alert(eval(data));
為什么會(huì)報(bào)錯(cuò)呢?data 是一個(gè)對(duì)象,按理說(shuō)應(yīng)該會(huì)彈出 Object[Object] 啊。 這是因?yàn)?,?dāng)我們寫(xiě)
{"username" : "justjavac"}
時(shí),它并不是一個(gè)對(duì)象。 因?yàn)槲覀冎烙幸环N表示數(shù)據(jù)的方法叫做 json(javascript對(duì)象表示法), 所以想當(dāng)然的認(rèn)為這應(yīng)該是一個(gè)對(duì)象。 其實(shí),在大部分編程語(yǔ)言中,大括號(hào)({})表示的不是對(duì)象,而是代碼塊,這段代碼其實(shí)等價(jià)于
{
"username" : "justjavac"
}
很顯然,"username" : "justjavac"
?并不是合法的語(yǔ)句。 然而解決方法也很簡(jiǎn)單,就是添加括號(hào)——分組操作符
({"username" : "justjavac"})
這樣就構(gòu)成了一個(gè)合法的表達(dá)式,當(dāng)我們進(jìn)行 json 對(duì)象解析的時(shí)候可以寫(xiě)如下代碼:
eval('(' + json + ')')
在表達(dá)式中,只能存在表達(dá)式,不能存在語(yǔ)句。
例如表達(dá)式
(var a = 4) + 4;
這段代碼將產(chǎn)生一個(gè)錯(cuò)誤,因?yàn)?var a = 4
?是一個(gè)語(yǔ)句, 而不是表達(dá)式——?對(duì)表達(dá)式求值必須返回值,但對(duì)語(yǔ)句求值則未必有返回值。
類(lèi)似的
if (var a = 0) {}
也產(chǎn)生錯(cuò)誤,因?yàn)?var a = 0
?是一條語(yǔ)句,而?語(yǔ)句沒(méi)有返回值。if 語(yǔ)句的語(yǔ)法結(jié)構(gòu)為
if (expression) {
statement;
statement;
……
}
因此
if (var a = 0) {}
是錯(cuò)誤的,但是
if (true) {
var a = 0;
}
則是正確的。
最后重申一下,每個(gè)表達(dá)式都有一個(gè)值。 理解了這個(gè),就可以很容易的理解 FP(函數(shù)式編程)的一些核心思想了。
更多建議: