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