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

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

原文(英文):http://www.2ality.com/2012/09/expressions-vs-statements.html
您可能感興趣的文章:
- javascript語句中的CDATA標簽的意義
- javascript while語句和do while語句的區(qū)別分析
- JavaScript中SQL語句的應(yīng)用實現(xiàn)
- Javascript技巧之不要用for in語句對數(shù)組進行遍歷
- 關(guān)于JavaScript的with 語句的使用方法
- javascript 循環(huán)語句 while、do-while、for-in、for用法區(qū)別
- javascript中break,continue和return語句用法小結(jié)
- javascript教程:關(guān)于if簡寫語句優(yōu)化的方法
- JavaScript 學(xué)習(xí)筆記之語句
相關(guān)文章
javascript學(xué)習(xí)總結(jié)之js使用技巧
本篇文章給大家分享javascript學(xué)習(xí)總結(jié)之js使用技巧,都是精華喔~小伙伴快來學(xué)習(xí)吧。2015-09-09
JavaScript 如何刪除小數(shù)點后的數(shù)字
這篇文章主要介紹了JavaScript 刪除小數(shù)點后的數(shù)字實例代碼,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-07-07
JavaScript高級程序設(shè)計 閱讀筆記(十七) js事件
IE中是冒泡型事件,即從最特定的事件目標到最不特定的事件目標2012-08-08
javascript基本數(shù)據(jù)類型和對象類型歸檔問題解析
這篇文章主要介紹了javascript基本數(shù)據(jù)類型和對象類型歸檔,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-03-03
Vue2.0+ElementUI實現(xiàn)表格翻頁的實例
下面小編就為大家?guī)硪黄猇ue2.0+ElementUI實現(xiàn)表格翻頁的實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10
JavaScript實現(xiàn)查找字符串中第一個不重復(fù)的字符
這篇文章主要介紹了JavaScript實現(xiàn)查找字符串中第一個不重復(fù)的字符,需要的朋友可以參考下2014-12-12
js判斷undefined類型,undefined,null, 的區(qū)別詳細解析
本篇文章主要是對js判斷undefined類型,undefined,null,NaN的區(qū)別進行了詳細的分析介紹,需要的朋友可以過來參考下,希望對大家有所幫助2013-12-12

