(二)語句與表達式 每個表達式都有一個值

2018-02-24 16:09 更新

雖然文章標題是『語句與表達式』,在這篇文章中,我將陳述一個觀點?每個表達式都有一個值。 在此之外,也會繼續(xù)表述這個『代碼之謎』系列的主題——數(shù)學與計算機之間被經(jīng)常忽略的矛盾。

簡單的講

  • "表達式"(expression)是一個單純的運算過程,總是有返回值;
  • "語句"(statement)是執(zhí)行某種操作,沒有返回值。

使用表達式也是函數(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ù)式編程)的一些核心思想了。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號