JavaScript中:表达式和语句的区别[译]

1.语句和表达式

JavaScript中的表达式和语句是有区别的.一个表达式会产生一个值,它可以放在任何需要一个值的地方,比如,作为一个函数调用的参数.下面的每行代码都是一个表达式:

myvar3 + xmyfunc("a", "b")语句可以理解成一个行为.循环语句和if语句就是典型的语句.一个程序是由一系列语句组成的.JavaScript中某些需要语句的地方,你可以使用一个表达式来代替.这样的语句称之为表达式语句.但反过来不可以:你不能在一个需要表达式的地方放一个语句.比如,一个if语句不能作为一个函数的参数.

2.其他语法

看看下面这两对类似的语法,搞懂这些后,能够帮助我们更好的理解语句和表达式之间的关系.

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()逗号运算符会计算前后两个表达式,然后返回右边表达式的计算结果.例如:

复制代码 代码如下:


> "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居然可以有独立的代码块(常见的代码块是依托于循环或者if语句的).下面的代码演示了这种代码块的作用:你可以给它设置一个标签然后跳出这个代码块.

复制代码 代码如下:


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 函数表达式和函数声明
下面的代码是一个函数表达式:

function () { }你还可以给这个函数表达式起一个名字,将它转变为一个命名(非匿名)的函数表达式:

function foo() { }这个函数的函数名(foo)只存在于函数内部,比如,可以用它来做递归运算:

复制代码 代码如下:


> var fac = function me(x) { return x <= 1 ? 1 : x * me(x-1) }
> fac(10)
3628800
> console.log(me)
ReferenceError: me is not defined



一个命名的函数表达式从表面上看起来,和一个函数声明并没有什么区别.但他们的效果是不同的:一个函数表达式产生一个值(一个函数).一个函数声明执行一个动作:将一个函数赋值给一个变量. 此外,只有函数表达式可以被立即调用,函数声明不可以.

3.3 解决冲突
从3.1和3.2可以看出,有些表达式和语句在表面上看不出有什么区别.也就意味着,相同的代码,出现在表达式上下文和出现在语句上下文会表现出不同的作用.通常情况下,这两种上下文是没有交集的.但是,如果是表达式语句的话,会有一个重叠:也就是说,会有一些表达式出现在语句上下文上.为了解决这种歧义,JavaScript语法禁止表达式语句以大括号或关键字"function"开头:

复制代码 代码如下:


ExpressionStatement :
[lookahead ∉ {"{", "function"}] Expression ;


那么,如果你想写一个以那些标志开头的表达式语句,该怎办呢? 你可以把它放在一个括号内部,这样并不会改变运行结果,只会确保该表达式被解析在表达式上下文中.让我们看两个例子.第一个例子:eval会按照语句上下文解析它的参数.如果你想让eval返回一个对象,你必须在对象字面量两边加上一个括号.

复制代码 代码如下:


> eval("{ foo: 123 }")
123
> eval("({ foo: 123 })")
{ foo: 123 }


第二个例子:下面的例子是一个立即执行的函数表达式.

复制代码 代码如下:


> (function () { return "abc" }())
'abc'


如果你省略了小括号,你会得到一个语法错误(函数声明不可以是匿名的):

复制代码 代码如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wddsjw.html