前言
表达式在 JavaScript 中是短语,那么语句(statement)就是 JavaScript 整句或命令。表达式计算出一个值,但语句用来执行以使某件事发生。
“使某件事发生”的一个方法是计算带有副作用的表达式。诸如赋值和函数调用这些有副作用的表达式,是可以作为单独的语句的,这种把表达式当做语句的用法也称做表达式语句(expression statement)。类似的语句还有声明语句(declaration statement),声明语句用来声明新变量或定义新函数。
另一种“使某件事发生”的方法是改变语句的默认执行顺序。默认情况下,JavaScript 解释器依照语句的编写顺序依次执行。JavaScript 中有很多语句和控制结构(control structure)来改变语句的默认执行顺序:
- 条件(conditional)语句,JavaScript 解释器可以根据一个表达式的值来判断是执行还是跳过这些语句,如 if 语句和 switch 语句。
- 循环(loop)语句,可以重复执行语句,如 while 和 for 语句。
- 跳转(jump)语句,可以让解释器跳转至程序的其他部分继续执行,如 break、return 和 throw 语句
表达式语句(掌握)
具有副作用的表达式是 JavaScript 中最简单的语句。赋值语句是一类比较重要的表达式语句,例如:
greeting="Hello"+name;
i*=3;
2
递增运算符(++)和递减运算符(--)和赋值语句有关。它们的作用是改变一个变量的值,就像执行一条赋值语句一样:
counter++;
delete 运算符的重要作用是删除一个对象的属性,所以,它一般作为语句使用,而不是作为复杂表达式的一部分:
delete o.x;
函数调用是表达式语句的另一个大类,例如:
alert(greeting);
window.close();
2
复合语句和空语句(掌握)
JavaScript 中还可以将多条语句联合在一起,形成一条复合语句(compound statement)。只须用花括号将多条语句括起来即可。因此,下面几行代码就可以当成一条单独的语句,使用在 JavaScript 中任何希望使用一条语句的地方:
{
x=Math.PI;
cx=Math.cos(x);
console.1og("cos(π)="+cx);
}
2
3
4
5
- 第一,语句块的结尾不需要分号。块中的原始语句必须以分号结束,但语句块不需要。
- 第二,语句块中的行都有缩进,这不是必需的,但整齐的缩进能让代码可读性更强,更容易理解。
- 最后,需要注意,JavaScript 中没有块级作用域,在语句块中声明的变量并不是语句块私有的。
//初始化一个数组a
for(i=0;i<a.length;a[i++]=0);
2
在这个循环中,所有的操作都在表达式 a[i++]=0 中完成,这里并不需要任何循环体。然而 JavaScript 需要循环体中至少包含一条语句,因此,这里只使用了一个单独的分号来表示一条空语句。
注意,在 for 循环、while 循环或 if 语句的右圆括号后的分号很不起眼,这很可能造成一些致命 bug,而这些 bug 很难定位到。例如,下面的代码的执行结果可能就不是程序作者想要的效果:
if((a==0)||(b==0));//糟糕!这一行代码什么都没做...
a=nul1;/这一行代码总是会执行
2
如果有特殊的目的需要使用空语句,最好在代码中添加注释,这样可以更清楚地说明这条空语句是有用的,例如:
for(i=o;i<a.length;a[i++]=0)/*empty*/;
声明语句(掌握)
var
var 语句用来声明一个或者多个变量,var 声明的变量是无法通过 delete 删除的。
如果 var 语句中的变量没有指定初始化表达式,那么这个变量的值初始为 undefined。
变量在声明它们的脚本或函数中都是有定义的,变量声明语句会被“提前”至脚本或者函数的顶部。但是初始化的操作则还在原来 var 语句的位置执行,在声明语句之前变量的值是 undefined。
需要注意的是,var 语句同样可以作为 for 循环或者 for/in 循环的组成部分(和在循环之外声明的变量声明一样,这里声明的变量也会“提前”)。
function
function 是要声明的函数的名称的标识符。函数名之后的圆括号中是参数列表,参数之间使用逗号分隔。当调用函数时,这些标识符则指代传入函数的实参。
函数体是由 JavaScript 语句组成的,语句的数量不限,且用花括号括起来。在定义函数时,并不执行函数体内的语句,它和调用函数时待执行的新函数对象相关联。注意,function 语句里的花括号是必需的,这和 while 循环和其他一些语句所使用的语句块是不同的,即使函数体只包含一条语句,仍然必须使用花括号将其括起来。
函数声明语句通常出现在 JavaScript 代码的最顶层,也可以嵌套在其他函数体内。但在嵌套时,函数声明只能出现在所嵌套函数的顶部。也就是说,函数定义不能出现在 if 语句、while 循环或其他任何语句中,正是由于函数声明位置的这种限制,ECMAScript 标准规范并没有将函数声明归类为真正的语句。有一些 JavaScript 实现的确允许在出现语句的地方都可以进行函数声明,但是不同的实现在细节处理方式上有很大差别,因此将函数声明放在其他的语句内的做法并不具备可移植性。
和通过 var 声明变量一样,函数定义语句中的函数被显式地“提前”到了脚本或函数的顶部。因此它们在整个脚本和函数内都是可见的。使用 var 的话,只有变量声明提前了——变量的初始化代码仍然在原来的位置。然而使用函数声明语句的话,函数名称和函数体均提前:脚本中的所有函数和函数中所有嵌套的函数都会在当前上下文中其他代码之前声明。也就是说,可以在声明一个 JavaScript 函数之前调用它。
和 var 语句一样,函数声明语句创建的变量也是无法删除的。但是这些变量不是只读的,变量值可以重写。
条件语句(掌握)
条件语句是通过判断指定表达式的值来决定执行还是跳过某些语句。这些语句是代码的 “决策点”,有时称为“分支”。如果说 JavaScript 解释器是按照代码的“路径”执行的,条件语句就是这条路径上的分叉点,程序执行到这里时必须选择其中一条路径继续执行。
if
需要注意的是,if 语句中括住 expression 的圆括号在语法上是必需的。JavaScript 语法规定,if 关键字和带圆括号的表达式之后必须跟随一条语句,但可以使用语句块将多条语句合并成一条。
else if
if/e1se 语句通过判断一个表达式的计算结果来选择执行两条分支中的一条。但当代码中有多条分支的时候该怎么办呢?一种解决办法是使用 else if 语句。elseif 语句并不是真正的 JavaScript 语句,它只不过是多条 if/else 语句连在一起时的一种惯用写法。
switch
当所有的分支都依赖于同一个表达式的值时,else if 并不是最佳解决方案。在这种情况下,重复计算多条 if 语句中的条件表达式是非常浪费的做法。
switch 语句正适合处理这种情况。关键字 switch 之后紧跟着圆括号括起来的一个表达式,随后是一对花括号括起来的代码块:
switch(expression){
statements
}
2
3
然而,switch 语句的完整语法要比这复杂一些。代码块中可以使用多个由 case 关键字标识的代码片段,case 之后是一个表达式和一个冒号,case 和标记语句很类似,只是这个标记语句并没有名字,它只和它后面的表达式关联在一起。当执行这条 switch 语句的时候,它首先计算 expression 的值,然后查找 case 子句中的表达式是否和 expression 的值相同(这里的“相同”是按照“===”运算符进行比较的)。如果找到匹配的 case,那么将会执行这个 case 对应的代码块。如果找不到匹配的 case,那么将会执行“default:”标签中的代码块。如果没有“default:”标签,switch 语句将跳过它的所有代码块。
switch(n){
case 1://如果n===1,从这里开始执行
//执行代码块1
break;//停止执行switch语句
case 2://如果n===2,从这里执行
//执行代码块2
break;//在这里停止执行switch语句
case 3://如果n===3,从这里执行
//执行代码块3
break;//在这里停止执行switch语句
default://如果所有的条件都不匹配
//执行代码块4
break;//在这里停止执行switch语句
}
2
3
4
5
6
7
8
9
10
11
12
13
14
如果没有 break 语句,那么 switch 语句就会从与 expression 的值相匹配的 case 标签处的代码块开始执行,依次执行后续的语句,一直到整个 switch 代码块的结尾。如果在函数中使用 switch 语句,可以使用 return 来代替 break,return 和 break 都用于终止 switch 语句,也会防止一个 case 语句块执行完后继续执行下一个 case 语句块。
循环(掌握)
while
while (expression) statement;
在执行 while 语句之前,JavaScript 解释器首先计算 expression 的值,如果它的值是假值,那么程序将跳过循环体中的逻辑 statement 转而执行程序中的下一条语句。反之,如果表达式 expression 是真值,JavaScript 解释器将执行循环体内的逻辑,然后再次计算表达式 expression 的值,这种循环会一直继续下去,直到 expression 的值为假值为止。
do/while
do/while 循环和 while 循环非常相似,只不过它是在循环的尾部而不是顶部检测循环表达式,这就意味着循环体至少会执行一次。do/while 循环的语法如下:
do
statement
while(expression);
do{
console.1og(a[i]);
}while(++i<len);
2
3
4
5
6
在 do/while 循环和普通的 while 循环之间有两点语法方面的不同之处。
首先,do 循环要求必须使用关键字 do 来标识循环的开始,用 while 来标识循环的结尾并进入循环条件判断。
其次,和 while 循环不同,do 循环是用分号结尾的。如果 while 的循环体使用花括号括起来的话,则 while 循环也不用使用分号做结尾。
for
for(initialize;test;increment)
statement
2
当然,有些循环会比这些例子更加复杂,而且循环中的一次迭代会改变多个变量。在 JavaScript 中,这种情况则必须用到逗号运算符,它将初始化表达式和自增表达式合并入一个表达式中以用于 for 循环:
var i,j;
for(i=0,j=10;i<10;i++,j--)
sum+=i*j;
2
3
for/in
for (variable in object) statement;
在执行 for/in 语句的过程中,JavaScript 解释器首先计算 object 表达式。如果表达式为 nu11 或者 undefined,JavaScirpt 解释器将会跳过循环并执行后续的代码。如果表达式等于一个原始值,这个原始值将会转换为与之对应的包装对象(wrapper object)(见 3.6 节)。否则,expression 本身已经是对象了。JavaScript 会依次枚举对象的属性来执行循环。然而在每次循环之前,JavaScript 都会先计算 variable 表达式的值,并将属性名(一个字符串)赋值给它。
var o = { x: 1, y: 2, z: 3 };
var a = [],
i = 0;
for (a[i++] in o /* empty*/);
2
3
4
其实,for/in 循环并不会遍历对象的所有属性,只有“可枚举”(enumerable)的属性才会遍历到。由 JavaScript 语言核心所定义的内置方法就不是“可枚举的”。比如,所有的对象都有方法 toString(),但 for/in 循环并不枚举 toString 这个属性。除了内置方法之外,还有很多内置对象的属性也是“不可枚举的”(nonenumerable)。
而代码中定义的所有属性和方法都是可枚举的。对象可以继承其他对象的属性,那些继承的自定义属性也可以使用 for/in 枚举出来。
如果 for/in 的循环体删除了还未枚举的属性,那么这个属性将不会再枚举到。
如果循环体定义了对象的新属性,这些属性通常也不会枚举到(然而,JavaScript 的有些实现是可以枚举那些在循环体中增加的继承属性的)。
属性枚举的顺序
ECMAScript 规范并没有指定 for/in 循环按照何种顺序来枚举对象属性。但实际上,主流浏览器厂商的 JavaScript 实现是按照属性定义的先后顺序来枚举简单对象的属性,先定义的属性先枚举。
在下列情况下,枚举的顺序取决于具体的实现(并且是非交互的):
- 对象继承了可枚举属性;
- 对象具有整数数组索引的属性;
- 使用 delete 删除了对象已有的属性;
- 使用 Object.defineProperty()或者类似的方法改变了对象的属性。
但当数组元素的索引是非数字或数组是稀疏数组(数组索引是不连续的)时它们则按照特定顺序枚举。
跳转(掌握)
标签语句
语句是可以添加标签的,标签是由语句前的标识符和冒号组成。break 和 continue 是 JavaScript 中唯一可以使用语句标签的语句。
mainloop:while(tokenl=nul1){
//忽略这里的代码..
continue mainloop;//跳转到下一次循环
//忽略这里的代码…
}
2
3
4
5
这里用做标签的 identifier 必须是一个合法的 JavaScript 标识符,而不能是一个保留字。标签的命名空间和变量或函数的命名空间是不同的,因此可以使用同一个标识符作为语句标签和作为变量名或函数名。
语句标签只有在它所起作用的语句(当然也可以在它的子句中)内是有定义的。一个语句标签不能和它内部的语句标签重名,但在两个代码段不相互嵌套的情况下是可以出现同名的语句标签的。带有标签的语句还可以带有标签,也就是说,任何语句可以有很多个标签。
break 语句
单独使用 break 语句的作用是立即退出最内层的循环或 switch 语句。
在 break 关键字和 labelname 之间不能换行。因为 JavaScript 可以给语句自动补全省略掉的分号,如果 break 关键字和标签之间有换行,JavaScript 解释器会认为你在使用 break 不带标签的最简形式,因此会在 break 后补充分号。
最后,需要注意的是,不管 break 语句带不带标签,它的控制权都无法越过函数的边界。比如,对于一条带标签的函数定义语句来说,不能从函数内部通过这个标签来跳转到函数外部。
continue 语句
continue 语句和 break 语句非常类似,但它不是退出循环,而是转而执行下一次循环。不管 continue 语句带不带标签,它只能在循环体内使用。在其他地方使用将会报语法错误。
在不同类型的循环中,continue 的行为也有所区别:
- 在 while 循环中,在循环开始处指定的 expression 会重复检测,如果检测结果为 true,循环体会从头开始执行。
- 在 do/while 循环中,程序的执行直接跳到循环结尾处,这时会重新判断循环条件,之后才会继续下一次循环。
- 在 for 循环中,首先计算自增表达式,然后再次检测 test 表达式,用以判断是否执行循环体。
- 在 for/in 循环中,循环开始遍历下一个属性名,这个属性名赋给了指定的变量。
需要注意 continue 语句在 while 和 for 循环中的区别,while 循环直接进入下一轮的循环条件判断,但 for 循环首先计算其 increment 表达式,然后判断循环条件。
return 语句
函数中的 return 语句既是指定函数调用后的返回值。return 语句只能在函数体内出现,如果不是的话会报语法错误。当执行到 return 语句的时候,函数终止执行,并返回 expression 的值给调用程序。
由于 JavaScript 可以自动插入分号,因此在 return 关键字和它后面的表达式之间不能有换行。
throw 语句
所谓异常(exception)是当发生了某种异常情况或错误时产生的一个信号。抛出异常,就是用信号通知发生了错误或异常状况。捕获异常是指处理这个信号,即采取必要的手段从异常中恢复。在 JavaScript 中,当产生运行时错误或者程序使用 throvw 语句时就会显式地抛出异常。使用 try/catch/finally 语句可以捕获异常。
throw expression;
expression 的值可以是任意类型的。可以抛出一个代表错误码的数字,或者包含可读的错误消息的字符串。当 JavaScript 解释器抛出异常的时候通常采用 Error 类型和其子类型,当然也可以使用它们。一个 Error 对象有一个 name 属性表示错误类型,一个 message 属性用来存放传递给构造函数的字符串。
function factorial(x){
//如果输入参数是非法的,则抛出一个异常
if(x<0)throw new Error("x不能是负数”);
//否则,计算出一个值,并正常地返回它
for(var f=1;x>1;f*=x,x--)/* empty*/;
return f;
}
2
3
4
5
6
7
当抛出异常时,JavaScript 解释器会立即停止当前正在执行的逻辑,并跳转至就近的异常处理程序。异常处理程序是用 try/catch/finally 语句的 catch 从句编写的,下一节会介绍它。
如果抛出异常的代码块没有一条相关联的 catch 从句,解释器会检查更高层的闭合代码块,看它是否有相关联的异常处理程序。以此类推,直到找到一个异常处理程序为止。如果抛出异常的函数没有处理它的 try/catch/finally 语句,异常将向上传播到调用该函数的代码。这样的话,异常就会沿着 JavaScript 方法的词法结构和调用栈向上传播。如果没有找到任何异常处理程序,JavaScript 将把异常当成程序错误来处理,并报告给用户。
try/catch/finally 语句
try/catch/finally 语句是 JavaScript 的异常处理机制。其中 try 从句定义了需要处理的异常所在的代码块。catch 从句跟随在 try 从句之后,当 try 块内某处发生了异常时,调用 catch 内的代码逻辑。catch 从句后跟随 finally 块,后者中放置清理代码,不管 try 块中是否产生异常,finally 块内的逻辑总是会执行。
尽管 catch 和 finally 都是可选的,但 try 从句需要至少二者之一与之组成完整的语句。try、catch 和 finally 语句块都需要使用花括号括起来,这里的花括号是必需的,即使从句中只有一条语句也不能省略花括号。
try{
//通常来讲,这里的代码会从头执行到尾而不会产生任何问题,
//但有时会抛出一个异常,要么是由throw语句直接抛出异常,
//要么是通过调用一个方法间接抛出异常
catch(e){
//当且仅当try语句块抛出了异常,才会执行这里的代码
//这里可以通过局部变量e来获得对Error对象或者抛出的其他值的引用
//这里的代码块可以基于某种原因处理这个异常,也可以忽略这个异常,
//还可以通过throw语句重新抛出异常
finally{
//不管try语句块是否抛出了异常,这里的逻辑总是会执行,终止try语句块的方式有:
//1)正常终止,执行完语句块的最后一条语句
//2)通过break、continue或return语句终止
//3)抛出一个异常,异常被catch从句捕获
//4)抛出一个异常,异常未被捕获,继续向上传播
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
关键字 catch 后跟随了一对圆括号,圆括号内是一个标识符。这个标识符具有块级作用域,它只在 catch 语句块内有定义。
通常状况下,解释器执行到 try 块的尾部,然后开始执行 finally 中的逻辑,以便进行必要的清理工作。当由于 return、continue 或 break 语句使得解释器跳出 try 语句块时,解释器在执行新的目标代码之前先执行 fnally 块中的逻辑。
如果在 try 中产生了异常,而且存在一条与之相关的 catch 从句来处理这个异常,解释器会首先执行 catch 中的逻辑,然后执行 finally 中的逻辑。如果不存在处理异常的局部 catch 从句,解释器会首先执行 finally 中的逻辑,然后向上传播这个异常,直到找到能处理这个异常的 catch 从句。
如果 finally 块使用了 return、continue、break 或者 throw 语句使程序发生跳转,或者通过调用了抛出异常的方法改变了程序执行流程,不管这个跳转使程序挂起还是继续执行,解释器都会将其忽略。例如,如果 fina1ly 从句抛出一个异常,这个异常将替代正在抛出的异常。如果 finally 从句运行到了 return 语句,尽管已经抛出了异常且这个抛出的异常还没有处理,这个方法依然会正常返回。
在没有 catch 从句的情况下 try 从句可以和 finally 从句一起使用。在这种情况下,finally 块只包含清理代码,不管 try 块中是否有 break、continue 或 return 语句,这里的代码一定会执行,回想一下,我们无法完全精确地使用 while 循环来模拟 for 循环,因为 continue 语句在两个循环中的行为表现不一致。如果使用 try/finally 语句,就能使用 while 循环来正确模拟包含 continue 的 for 循环:
while (test) {
try {
body;
} finally {
increment;
}
}
2
3
4
5
6
7
然而需要注意的是,当 body 包含 break 语句时,while 循环和 for 循环便有了更微妙的区别,(造成了一次额外的自增运算),因此即便使用了 finally 从句,使用 while 来完全模拟 for 循环依然是不可能的。
其他语句类型(了解)
with 语句
作用域链(scope chain)是一个可以按序检索的对象列表,通过它可以进行变量名解析。with 语句用于临时扩展作用域链,它具有如下的语法:
with(object)
statement
2
这条语句将 object 添加到作用域链的头部,然后执行 statement,最后把作用域链恢复到原始状态。
在
严格模式中是禁止使用 with 语句的,并且在非严格模式里也是不推荐使用 with 语句的,尽可能避免使用 with 语句。那些使用 with 语句的 JavaScript 代码非常难于优化,并且同没有使用 with 语句的代码相比,它运行得更慢。
在对象嵌套层次很深的时候通常会使用 with 语句来简化代码编写。例如,在客户端 JavaScript 中,可能会使用类似下面这种表达式来访问一个 HTML 表单中的元素:
document.forms[o].address.value;
如果这种表达式在代码中多次出现,则可以使用 with 语句将 form 对象添加至作用域链的顶层:
with(document.forms[o]){
//直接访问表单元素,例如:
name.value="";
address.value="";
email.value="";
}
2
3
4
5
6
这种方法减少了大量的输入,不用再为每个属性名添加 document.forms[o]前缀。这个对象临时挂载在作用域链上,当 JavaScript 需要解析诸如 address 的标识符时,就会自动在这个对象中查找。当然,不使用 with 语句的等价代码可以写成这样:
var f = document.forms[o];
f.name.value = '';
f.address.value = '';
f.email.value = '';
2
3
4
只有在查找标识符的时候才会用到作用域链,创建新的变量的时候不使用它,看一下下面这行代码:
with(o)x=1;
如果对象 o 有一个属性 x,那么这行代码给这个属性赋值为 1。但如果 o 中没有定义属性 x,这段代码和不使用 with 语句的代码 x=1 是一模一样的。它给一个局部变量或者全局变量 x 赋值,或者创建全局对象的一个新属性。with 语句提供了一种读取。的属性的快捷方式,但它并不能创建 o 的属性。
debugger 语句
debugger 语句通常什么也不做。然而,当调试程序可用并运行的时候,JavaScript 解释器将会(非必需)以调式模式运行。实际上,这条语句用来产生一个断点(breakpoint),JavaScript 代码的执行会停止在断点的位置,这时可以使用调试器输出变量的值、检查调用栈等。
"use strict"
“use strict”是 ECMAScript5 引入的一条指令。指令不是语句(但非常接近于语句)。“use strict”指令和普通的语句之间有两个重要的区别:
- 它不包含任何语言的关键字,指令仅仅是一个包含一个特殊字符串直接量的表达式(可以是使用单引号也可以使用双引号),对于那些没有实现 ECMAScript5 的 JavaScript 解释器来说,它只是一条没有副作用的表达式语句,它什么也没做。将来的 ECMAScript 标准希望将 use 用做关键字,这样就可以省略引号了。
- 它只能出现在脚本代码的开始或者函数体的开始、任何实体语句之前。但它不必一定出现在脚本的首行或函数体内的首行,因为“use strict”指令之后或之前都可能有其他字符串直接量表达式语句,并且 JavaScript 的具体实现可能将它们解析为解释器自有的指令。在脚本或者函数体内第一条常规语句之后字符串直接量表达式语句只当做普通的表达式语句对待;它们不会当做指令解析,它们也没有任何副作用。
严格模式(了解)
- 在严格模式中禁止使用 with 语句。
- 在严格模式中,所有的变量都要先声明,如果给一个未声明的变量、函数、函数参数、catch 从句参数或全局对象的属性赋值,将会抛出一个引用错误异常(在非严格模式中,这种隐式声明的全局变量的方法是给全局对象新添加一个新属性)。
- 在严格模式中,调用的函数(不是方法)中的一个 this 值是 undefined。(在非严格模式中,调用的函数中的 this 值总是全局对象)。可以利用这种特性来判断 JavaScript 实现是否支持严格模式:
var hasstrictMode=(function(){"use strict";return this===undefined}());
- 同样,在严格模式中,当通过 ca11()或 apply()来调用函数时,其中的 this 值就是通过 ca11()或 apply()传入的第一个参数(在非严格模式中,nu11 和 undefined 值被全局对象和转换为对象的非对象值所代替)。
- 在严格模式中,给只读属性赋值和给不可扩展的对象创建新成员都将抛出一个类型错误异常(在非严格模式中,这些操作只是简单地操作失败,不会报错)。
- 在严格模式中,传入 eva1()的代码不能在调用程序所在的上下文中声明变量或定义函数,而在非严格模式中是可以这样做的。相反,变量和函数的定义是在 eval()创建的新作用域中,这个作用域在 eval()返回时就弃用了。
- 在严格模式中,函数里的 arguments 对(见 8.3.2 节)拥有传入函数值的静态副本。在非严格模式中,arguments 对象具有“魔术般”的行为,arguments 里的数组元素和函数参数都是指向同一个值的引用。
- 在严格模式中,当 delete 运算符后跟随非法的标识符(比如变量、函数、函数参数)时,将会抛出一个语法错误异常(在非严格模式中,这种 delete 表达式什么也没做,并返回 false)。
- 在严格模式中,试图删除一个不可配置的属性将抛出一个类型错误异常(在非严格模式中,delete 表达式操作失败,并返回 false)。
- 在严格模式中,在一个对象直接量中定义两个或多个同名属性将产生一个语法错误(在非严格模式中不会报错)。
- 在严格模式中,函数声明中存在两个或多个同名的参数将产生一个语法错误(在非严格模式中不会报错)。
- 在严格模式中是不允许使用八进制整数直接量(以 0 为前缀,而不是 0x 为前缀)的(在非严格模式中某些实现是允许八进制整数直接量的)。
- 在严格模式中,标识符 eval 和 arguments 当做关键字,它们的值是不能更改的。不能给这些标识符赋值,也不能把它们声明为变量、用做函数名、用做函数参数或用做 catch 块的标识符。
- 在严格模式中限制了对调用栈的检测能力,在严格模式的函数中,arguments.caller 和 arguments.callee 都会抛出一个类型错误异常。严格模式的函数同样具有 caller 和 arguments 属性,当访问这两个属性时将抛出类型错误异常(有一些 JavaScript 的实现在非严格模式里定义了这些非标准的属性)。