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'

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


代码如下:

> function () { return "abc" }()
SyntaxError: function statement requires a name

如果你添加上函数名,还会得到一个语法错误(函数声明不能被理解执行):


代码如下:

> function foo() { return "abc" }()
SyntaxError: syntax error

另外一个能让表达式在表达式上下文上被解析的办法是使用一元运算符,比如 + 或者 !.但是,和使用括号不同的是,这些操作符会改变表达式的运行结果.如果你不关心结果的话,完全可以使用:


代码如下:

> +function () { console.log("hello") }()
hello
NaNNaN

是+作用在函数执行后的返回值undefined上的结果.

译者注:我觉的没翻译明白,所以用拙劣的水平画了张图.


原文(英文):http://www.2ality.com/2012/09/expressions-vs-statements.html

(0)

相关推荐

  • 关于JavaScript的with 语句的使用方法

    用过 Java 和 .NET 的同学对包或命名空间的概念应该不会陌生, 正因为有这个概念, 使代码的简洁易读得到了保证. 不知 JavaScript 设计之初是如何定位 with 语句的, 个人觉得它们之间有一定的相似度. 如: 复制代码 代码如下: apple.banana.candy.dog.egg.fog.god.huh.index = 0; doSomething(apple.banana.candy.dog.egg.fog.god.huh.index); 利用 with 语句, 可以写

  • JavaScript 学习笔记之语句

    一.条件分支语句:if 基本格式: if (<表达式1>){     <语句组1> }else if (<表达式2>){     <语句组2> }else{     <语句组3> } 执行流程: 二.循环语句 2.1前测试循环语句:在循环体内的代码被执行之前就对出口条件求值. 2.1.1while语句 基本格式: do {     <语句组> } while (<表达式>) 执行流程: 2.1.2 for语句 基本格式:

  • Javascript技巧之不要用for in语句对数组进行遍历

    一,为什么不要用for in语句 jqModal这个jquery插件估计很多人都使用过,在jqModal源码内部,有一个函数为hs,其中有个嵌套循环如下, 复制代码 代码如下: for(var i in {jqmShow:1,jqmHide:1}) for(var s in this[i]) if(H[this[i][s]]) H[this[i][s]].w[i](this); return F; } 第一个for in遍历的目标是个匿名对象,没有问题. 第二个for in遍历,根据上下文确认t

  • javascript中break,continue和return语句用法小结

    由于最近一直在看javascript,下面简要说一下它们三个在javascript的一些用法 break语句: break语句会使运行的程序立刻退出包含在最内层的循环或者退出一个switch语句.由于它是用来退出循环或者switch语句,所以只有当它出现在这些语句时,这种形式的break语句才是合法的. 如果一个循环的终止条件非常复杂,那么使用break语句来实现某些条件比用一个循环表达式来表达所有的条件容易得多. for(var i=1;i [Ctrl+A 全选 注:如需引入外部Js需刷新才能

  • javascript while语句和do while语句的区别分析

    while语句: 复制代码 代码如下: var i = 1;  while(i<10)  {      document.write(i);      i++;  } do while语句:  复制代码 代码如下: var i = 1;  do  {      document.write(i);      i++; }while(i<10); 从上边例子中我们来分析它们的两点不同: 1.因为while语句总是先检测循环表达式,所以它的循环体可能一次都不执行:而do/while语句是在循环底部

  • javascript教程:关于if简写语句优化的方法

    UglifyJS是一个对javascript进行压缩和美化的工具,在它的文档说明中,我看到了几种关于if语句优化的方法.尽管我还没使用它去做一些尝试性的测试,但从这里可以看到它的确对js作了美化的工作.也许有人认为if语句就那么简单,能优化到什么程度?但是看看以下的几种方式,你也许会改变看法. 一.使用常见的三元操作符 if (foo) bar(); else baz(); ==> foo?bar():baz();if (!foo) bar(); else baz(); ==> foo?baz

  • JavaScript中SQL语句的应用实现

    比如对javascript数组的排序 还有对数组数据的删选以及分组 所以,后来兴致以上来. 一发不可收拾. 写了一个能在javascript中应用的 SQL 库 后来又想,怎么不能用javascript直接连接数据库呢? 又做了一个javascript直连Sql数据的类库 后来,又想到其实还可以用SQL语句来操作HTML DOM模型 再再再后来,又看到了HTML5中对web DB的实现 所以对webDB,就是chrome和safari中的sqlite的封装 于是乎就有了: 1.从服务器上获取数据

  • javascript 循环语句 while、do-while、for-in、for用法区别

    前两个唯一的差别就是循环和判断的顺序不同,do-while比while多循环一次,我就不举例了. for循环相信大家也熟的不能再熟了,我们就看for-in这一句. 这个其实是针对数组的,js中数组的初始化也挺奇特的比如我们在script结点里写:(另外注意下数组的初始化,用的是中括号) "); var a=[3,4,5,7]; for(var test in a){ document.write(test+": "+a[test]+""); } -->

  • javascript语句中的CDATA标签的意义

    看到这样一串代码: <SCRIPT type=text/JavaScript> <!--//--><![CDATA[//><!-- var spaceStaticData={               style: '/style/common/',         hostId: 2241772,        hostPath:'',        hostName: 'mycm22',         visitorName:'mycm22',      

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

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

  • JavaScript中的return语句简单介绍

    return语句在js中非常的重要,不仅仅具有返回函数值的功能,还具有一些特殊的用法,下面就结合实例简单介绍一下return语句的作用. 一.用来返回控制和函数结果: 通常情况,return语句对于一个函数是很有必要的,因为往往需要函数在一系列的代码执行后会得到一个期望的返回值,而此值就是通过return语句返回,并且将控制权返回给主调函数. 语法格式: return 表达式 代码实例如下: function add(){ var a=1; var b=2; return a+b; } func

  • JavaScript中object和Object的区别(详解)

    JavaScript中object和Object有什么区别,为什么用typeof检测对象,返回object,而用instanceof 必须要接Object呢 这个问题和我之前遇到的问题非常相似,我认为这里有两个问题需要解决,一个是运算符new的作用机制,一个是function关键字和Funtion内置对象之间的区别.看了一些前辈的博客和标准,这里帮提问者总结一下. 1.new new运算符的作用是创建一个对象实例.这个对象可以是用户自定义的,也可以是带构造函数的一些系统自带的对象.如果 new

  • JavaScript中undefined和null的区别

     JavaScript中undefined和null的区别 JavaScript两个表示"无"的值:undefined和null.我在平时只是null用的多一点,undefined只是在报错中经常遇到.下面针对这两个数据类型的异同做一下详细的比较. 1.undefined和null在if语句中,都会被自动转为false,相等运算符直接报告两者相等. !null==!undefined==true 2.null表示"没有对象",即该处不应该有值.典型用法是: (1)

  • JavaScript中click和onclick本质区别与用法分析

    本文实例讲述了JavaScript中click和onclick本质区别与用法.分享给大家供大家参考,具体如下: 原生javascript的click在w3c里边的阐述是DOM button对象,也是html DOM click() 方法,可模拟在按钮上的一次鼠标单击. button 对象代表 HTML 文档中的一个按钮.button元素没有默认的行为,但是必须有一个 onclick 事件句柄以便使用. 语法:buttonObject.click() <html> <head> &l

  • JavaScript中的标签语句用法分析

    本文实例分析了JavaScript中的标签语句用法.分享给大家供大家参考.具体分析如下: 最近在看w3school,然后看到js部分, <!DOCTYPE html> <html> <body> <script> cars=["BMW","Volvo","Saab","Ford"]; list: { document.write(cars[0] + "<br>

  • javascript中局部变量和全局变量的区别详解

    javascript有两种变量:局部变量和全局变量.当然,我们这篇文章是帮助大家真正的区别这两种变量. 首先,局部变量是指只能在本变量声明的函数内部调用.全局变量时整个代码中都可以调用的变量.当然,单单从字面上理解肯定是不清楚的,下面我详细的介绍下: 大家都知道,变量是需要用var关键字声明的.但是javascript中也可以隐式的使用变量,就是不用声明,直接使用.而且,千万注意,javascript把隐式声明的变量总是当成全局变量来使用的. 例如: 复制代码 代码如下: function my

  • Javascript中For In语句用法实例

    本文实例讲述了Javascript中For In语句用法.分享给大家供大家参考.具体如下: <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>For In 语句</title> <

  • javascript中call()、apply()的区别

    call().apply()的区别: 相同点: 1.call()和apply()都可以用来间接调用函数,都可以显式调用所需的this.即,任何函数可以作为任何对象的方法来调用. 2.两个方法都可以指定调用实参. 区别: call()和apply()的基本区别:在于将参数传递给函数. call():使用其自有的实参列表作为函数的参数: apply():要求以数组的形式传入参数. function track(o,m){ var original =o[m]; o[m] =function( ){

  • JavaScript中callee和caller的区别与用法实例分析

    本文实例讲述了JavaScript中callee和caller的区别与用法.分享给大家供大家参考,具体如下: 1.callee 在函数的内部,有两个特殊的对象:arguments和this.其中arguments是一个类似数组的对象,包含着传入函数的所有参数. 虽然arguments的主要用途是保存函数参数,但这个对象有一个属性--callee,该属性是一个指针,指向拥有这个arguments对象的函数 所以callee的作用就是来指向当前对象 看一个阶层函数的例子就会明白他的用途了: /* *

随机推荐