3.20 加性操作符
3.20.1 加法
加法操作符(+)的用法如下:
如果两个操作符都是数值,执行常规的加法计算,然后根据下列规则返回结果:
如果有一个操作数是NaN,则结果是NaN;
如果是Infinity 加 Infinity ,则结果是Infinity;
如果是-Infinity 加 -Infinity ,则结果是-Infinity;
如果是Infinity 加 -Infinity ,则结果是NaN;
如果是+0加+0,则结果是+0;
如果是-0加-0,则结果是-0;
如果是+0加-0,则结果是+0;
不过如果有一个操作数是字符串,那么就要应用下列规则;
如果两个操作数都是字符串,则将第二个操作数与第一个操作数拼接起来。
如果只有一个操作数是字符串,则将另一个操作数转换为字符串,然后将两个字符串拼接起来。
如果有一个操作数是对象、数值或布尔值,则调用它们的toString()方法取得相应的字符串值,然后再应用前面关于字符串的规则。对于undefined和null,则分别调用String()函数并取得字符串“undefined”和“null”。
var result=5+5;
alert(result); //结果10
var result2=5+"5";
alert(result2); //结果字符串"55"
var num1=5;
var num2=10;
var message="the sum of 5 and 10 is "+num1+num2;
alert(message); //结果是字符串"the sum of 5 and 10 is 510"
如果想先计算后面的数值可以用下面的方法
var num1=5;
var num2=10;
var message="the sum of 5 and 10 is "+(num1+num2);
alert(message); //结果是字符串"the sum of 5 and 10 is 15"
3.20.2 减法减法操作符(-)是另一个极为常用的操作符,其用法如下所示:
var result=3-2;
与加法操作符类似,ECMAScript中的减法操作符在出来各种数据类型转换时,通用需要遵循一些特殊规则,如下所示:
如果两个操作符都是数值,执行常规的减法计算,然后根据下列规则返回结果:
如果有一个操作数是NaN,则结果是NaN;
如果是Infinity 减 Infinity ,则结果是NaN;
如果是-Infinity 减 -Infinity ,则结果是NaN;
如果是Infinity 减 -Infinity ,则结果是Infinity;
如果是-Infinity 减 Infinity ,则结果是-Infinity;如果是+0减+0,则结果是+0;
如果是-0减0,则结果是-0;
如果是-0减-0,则结果是+0;
如果有一个操作数是字符串、布尔值、null 或 undefined,则先在后台调用Number()函数将其转换位数值,然后再根据前面的规则执行减法运算。如果转换的结果是NaN,则减法的结果就是NaN;
如果有一个操作数是对象,则调用对象的valueOf()方法以取得表示该对象的数值。如果得到的值是NaN,则减法的结果就是NaN。如果对象没有valueOf()方法,则调用toString()方法并将得到的字符串转换为数值。
如: var result=5-true; //结果是4 true被转换成了1
var result2=NaN-1; //结果是NaN
var result3=5-3; //结果是2
var result4=5-""; //结果是5 空字符串转换成了0
var result5=5-"2"; //结果是3 "2"转换成了2
var result6=5-null; //结果是5 null转换成了0
3.21 关系操作符小于(<)、大于(>)、小于等于(<=)和大于等于(>=)这几个关系操作符用于对两个值进行比较,比较的规则与我们在数学课上所学的一样。这几个操作符都返回一个布尔值,如: var result= 5> 3; //true
var result=5<3; //false
与ECMAScript中的其他操作符一样,当关系操作符的操作数使用了非数值时,也要进行数据转换或完成某些奇怪的操作。以下就是相应的规则。
如果两个操作数都是数值,则执行数值比较。
如果两个操作数都是字符串,则比较两个字符串对应的字符编码值。
如果一个操作数是数值,则将另一个操作数转换为一个数值,然后执行数值比较。
如果一个操作数是对象,则调用这个对象的valueOf()方法,用得到的结果按照前面的规则进行比较。如果对象没有valueOf()方法,则调用toString()方法,并用得到的结果根据前面的规则执行进行比较。
如果一个操作数是布尔值,则先将其转换为数值,然后再执行比较。
在使用关系操作符比较两个字符串时,会执行一种奇怪的操作。在比较字符串时,实际比较的是两个字符串中对应位置的每个字符的字符编码值。经过比较,返回布尔值。
由于大写字母的字符编码全部肖也小邪恶字母的字符编码,因此会出现下列奇怪现象:
var result= "Brick" < "alphabet"; //true
如果真正按照字幕版顺序比较字符串,就必须把两个操作数转换位相同的大小写形式(全部大写或全部小写),然后再执行比较,如:
var result ="Brick".toLowerCase() < "alphabet".toLowerCase(); //false
另一种奇怪的现象发生在比较两个数字字符串的情况下,比如:
var result= "23" < "3" ; //true
因为两个操作数都是字符串,而字符串比较的是字符编码(“2”的字符编码是50,而“3”的字符编码是51)。改成下面结果就正常了:
var result="23" < 3; //false
此时字符串“23”会被转换成数值23然后跟3比较。
如果字符串不能转换成一个合理的数值呢?如:
var result ="a " < 3; //false 因为“a”被转换成了NaN
由于a不能转换成合理的数值,因此被转换成了NaN。根据规则,任何操作数与NaN进行关系比较,结果都是false。于是,出现下面这个有意思的现象:
var result1=NaN < 3; //false
var result2=NaN >=3; //false
3.22 相等操作符
确定两个变量是否相等是编程中的一个非常重要的操作。
3.22.1 相等和不相等
ECMAScript中的相等操作符由两个等于号(==)表示,如果两个操作数相等,则返回true。而不相等操作符由感叹号后跟等于号(!=)表示,如果两个操作数不相等,则返回true。这两个操作符都会先转换操作数(通常称为强制转型),然后再比较它们的相等性。
在转换不同的数据类型时,相等和不相等操作符遵循下列规则:
如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值——false转换为0,true转换为1。
如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值。
如果一个操作数是对象,另一个不是,则调用对象的valueOf()方法,用得到的基本类型按照前面的规则进行比较。
这两个操作符在进行比较时要遵循下列规则。
null和undefined是相等的。
要比较相等性之前,不能将null和undefined转换成其他任何值。
如果有一个操作数是NaN,则相等操作符返回false,而不相等操作符返回true。重要提示:即使两个操作数都是NaN,相等操作符也返回false;因为按照规则,NaN不等于NaN。
如果两个操作数都是对象,则比较它们是不是同一个对象。如果俩个个操作数都指向同一个对象,则相等操作符返回true;否则返回false。
下表列出一些特殊情况及比较结果:
表达式 值
null == undefined true
"NaN" == NaN false
5 == NaN false
NaN == NaN false
NaN != NaN true
false == 0 true
true == 1 true
true ==2 false
undefined ==0 false
null ==0 false
"5" == 5 true
3.22.2 全等和不全等
除了在比较之前不转换操作数之外,全等和不全等操作符与相等和不相等操作符没有什么区别。全等操作符由3个等于号(===)表示,它只在两个操作数未经转换就相等的情况下返回true。
如: var result1=("55" ==55) //true
var result2=("55" === 55) //false
不全等操作符由一个叹号后跟两个等于号(!==)表示,它在两个操作数未经转换就不相等的情况下返回true。
如: var result1=("55" !=55) //false //因为转换后相等
var result2=("55" !== 55) //true
记住:null==undefined 会返回true,但null===undefined 会返回 false,因为它们是不同类型的值。
3.23 条件操作符
条件操作符应该算是ECMAScript中最灵活的一种操作符了,而且它遵循与java中的条件操作符相同的语法形式。
如: variable = boolean_expression ? true_value : false_value ;
本质上。这行代码的含义就是基于对boolean_expression求值的结果,决定给变量variable赋什么值。如果求值结果是true,则给变量variable赋true_value值,如果求值结果是false,则给变量variable赋false_value值。
再如: var max=(num1 > num2) ? num1 : num2 ;
在这个例子中,max将会保存一个最大的值。这个表达式的意思是:如果num1大于num2(关系表达式返回true),则将num1的值赋给max;如果num1小于等于num2(关系表达式返回false),则将num2赋值给max。
3.24 赋值操作符
简单的赋值操作符由等于号(=)表示,其作用就是把右侧的值赋给左侧的变量。
如: var num = 10 ;
如果在等于号(=)前面再添加乘性操作符、加性操作符或位操作符,就可以完成复合赋值操作。这种复合赋值操作相当于是对下面常规表达式的简写形式:
var num = 10;
num = num +10;
其中第二行代码可以用一个复合赋值来代替:
var num = 10;
num + =10;
每个主要算术操作符(以及个别的其他操作符)都有对应的复合赋值操作符。这些操作符如下:
乘/赋值 (*=);
除/赋值 (/=);
模/赋值 (%=);
加/赋值 (+=);
减/赋值 (-=);
左移/赋值 (<<=);
有符号右移/赋值 (>>=);
无符号右移/赋值 (>>>=);
设计这些操作符的主要目的就是简化赋值操作。使用它们不会带来任何性能的提升。
3.25 逗号操作符
使用逗号操作符可以在一条语句中执行多个操作。
如:var num1=1, num2=2, num3=3;
3.26 语句
3.26.1 if语句
大多数变成语言中最为常用的一个语句就是if语句,以下是if语句的语法:
if (condition) statement1 else statement2
其中的condition(条件)可以是任意表达式;而且对这个表达式求值的结果不一定是布尔值。ECMAScript会自动调用Boolean()转换函数将这个表达式的结果转换为一个布尔值。如果对condition求值的结果是true,则执行statement1(语句1),如果对condition求值的结果是false,则执行statement2(语句2)。而且这两个语句既可以是一行代码,也可以是一个代码库(以一对花括号括起来的多行代码)。
如:if(i > 25){
alert("Greater than 25");
}
else if(i<0){
alert("Less than 0.");
}
else{
alert("Less than or equal to 25");
}
3.26.2 do-while 语句
do-while 语句是一种后测试循环语句,在对条件表达式求值之前,循环体内的代码至少会被执行一次。以下是do-while 语句的语法:
do{
statement
}while(expression);
下面是一个示例:
var i =0;
do{
i+=2;
}while(i<10);
alert(i);
do-while循环语句最常用于循环体中的代码至少要被执行一次的情形。
3.26.3 while 语句
while语句属于前测试循环语句,也就是说,在循环体内的代码被执行之前,就会被出口条件求值。因此循环体内的代码有可能永远不会被执行。以下是while语句的语法:
while(expression) statement
下面是一个示例:
var i=0;
while(i <10){
i+=2;
}
在这个例子中,i初始值为0,每次循环+2。而只有i的值小于10,循环就会继续执行下去。
3.26.4 for 语句
for语句也是一种前测试循环语句,但它具有在执行循环之前初始化变量和定义循环后要执行的代码的能力。以下是for语句的语法:
for(initialization; expression; post-loop-exoression) statement
下面是一个示例:
var count=10;
for(var i=0; i<count; i++){
alert(i);
}
以上代码定义了变量i的初始值为0。只有当条件表达式(i<count)返回true的情况下才会进入for循环,因此也有可能不会执行循环体中的代码。如果执行了循环体中的代码,则一定会对循环后的表达式(i++)求值,即递增i的值。这个for循环语句与下面的while语句的功能相同:
var count=10;
var i=0;
while(i<count){
alert(i);
i++;
}
使用while循环做不到的,使用for循环也做不到。
有必要指出,在for循环的变量初始化表达式中,也可以不使用var关键字。
var count=10;
for(i=0; i<count; i++){
alert(i);
}
3.26.5 for-in语句for-in语句是一种精准的迭代语句,可以用来枚举对象的属性。以下是for-in语句的语法:
for ( property in expression) statement
下面是一个示例:
for(var propName in window){
document.write(propName);
}
在这个例子中,我们使用for-in循环来显示了BOM中window对象的所有属性。每次执行循环时,都会将window对象中存在的一个属性名赋值给变量propName。这个过程会一直持续到对象中的所有属性都被枚举一遍为止。与for语句类似,这里控制语句中的var操作符也不是必需的。但是,为了保证使用局部变量,我们推荐上面例子中的这种做法。
ECMAScript对象的属性没有顺序。因此,通过for-in循环输出的属性名的顺序是不可预测的。具体来讲,所有属性都会被返回一次,但返回的先后次序可能因浏览器而异。
但是如果表示迭代的对象的变量值为null或undefined,for-in语句会抛出错误。ECMAScrip5更正了这一行为;对这种情况不再抛出错误,而只是不执行循环体。为了保证最大限度的兼容性,建议在使用for-in循环之前,先检测确认该对象的值不是null或undefined。
3.26.6 label语句
使用label语句可以在代码中添加标签,以便将来使用。以下是label语句的语法:
label : statement
下面是一个示例:
start: for(var i=0; i< count; i++){
alert(i);
}
这个例子中定义的start标签可以在讲啦由break或continue语句引用。加标签的语句一般都要与for语句等循环语句配合使用。
3.26.7 break 和 continue 语句
break 和 continue 语句用于在循环中精确地控制代码的执行。其中,break语句会立即退出循环,强制继续执行循环后没的语句。而continue语句虽然也是立即退出循环,但退出循环后会从循环的顶部继续执行。请看下面的例子:
var num=0;
for(var i=1; i<10; i++){
if(i%5==0){
break;
}
num++;
}
alert(num); //4
这个例子中的for循环会将变量i由1递增值10。在循环体内,有一个if语句检查i的值是否可以被5整除(使用求模操作符)。如果是,则执行break语句退出循环。另一方面,变量num从0开始,用于记录循环执行的次数。在执行break语句之后,要执行的下一环代码是alert()函数,结果显示4。也就是说,在变量i等于5时,num++总共执行了4次;而break语句的执行,导致了循环在num再次递增之前就退出了。
var num=0;
for(var i=1; i<10; i++){
if(i%5==0){
continue;
}
num++;
}
alert(num); //8
例子的结果是8,也就是num++总共执行了8次。当变量i等于5时,循环会在num再次递增之前退出,但接下来执行的是下一次循环,即i的值等于6的循环。于是,循环又继续执行,直到i等于10时自然结束。而num的最终值之所以是8,是因为continue语句导致它少递增了一次。
var num=0;outermost:
for(var i=0; i<10; i++){
for(var j=0; j<10; j++){
if(i == 5 && j==5){
break outermost;
}
num++;
}
}
alert(num); //55
在这个例子中,outermost标签表示外部的for语句。如果每个循环正常执行10次,则num++语句就会正常执行100次。换句话说,如果两个循环都自然结束,num的值应该是100。但内部循环中的break语句带了一个参数:要返回到的标签。添加这个标签的结果将导致break语句不仅会退出内部的for语句(即使用变量j的循环),而且也会退出外部的for语句(即使用变量i的循环)。为此,当变量i和j都等于5时,num的值是55。同样continue语句也可以像这样与label语句联用,如下面的例子:
var num=0;
outermost:
for(var i=0; i<10; i++){
for(var j=0; j<10; j++){
if(i == 5 && j==5){
continue outermost;
}
num++;
}
}
alert(num); //95
在这种情况下,continue语句会强制继续执行循环——退出内部循环,执行外部循环。当j是5时,continue语句执行,而这也就意味着内部循环少执行了5次,因此num的值是95。虽然联用break、continue 和label语句能够执行复杂的操作,但如果使用过度,也会给调试带来麻烦。再此,我们提议如果使用label语句,一定要使用描述性的标签,同时不要嵌套太多的循环。
3.26.8 with语句
with语句的作用是将代码的作用域设置到一个特定的对象中。with语句的语法如下:
with (expression) statement;
定义with语句的目的主要是为了简化多次编写同一个对象的工作,如下:
var qs = location.search.substring(1);
var hostName= location.hostname;
var url = location.href;
上面几行代码都包含location对象。如果使用with语句,可以把上面的代码改写成如下所示:
with(location){
var qs=search.substring(1);
var hostName= hostname;
var url = href;
}
在这个重写后的例子中,使用with语句关联了location对象。这意味着在with语句的代码块内部,每个变量首先被认为是一个局部变量,而如果在局部环境中找不到该变量的定义,就会查询location对象中是否有同名的属性。如果发现了同名属性,则以location对象属性的值作为变量的值。
严格模式下不允许使用with语句,否则将视为语法错误。
由于大量使用with语句会导致性能下降,同时也会给调试代码造成困难,因此在开发大型应用程序时,不建议使用with语句。
3.26.9 switch 语句
switch语句与if语句的关系最为密切,而且也是在其他语言中普遍使用的一种流控制语句。
switch(expression){
case value : statement
break;
case value : statement
break;
case value : statement
break;
default: statement}
switch 语句中的每一种庆幸(case)的含义是:“如果表达式等于这个值(value),则执行后面的语句(statement)”。而break关键字会导致代码执行流跳出switch语句。如果省略break关键字,就会导致执行完当前case后,继续执行下一个case。最后的default关集资则用于在表达式不匹配前面任何一种情形的时候,执行机动代码(因此,也相当于一个else语句)。
从根本上讲,switch语句就是为了让开发人员免于编写像下面这样的代码:
if(i==25){
alert("25");
}else if{(i==35)
alert("35");
}else if{(i==45)
alert("45");
}else{
alert("other");
}
而与此等价的switch语句如下:
switch(i){
case 25:
alert("25");
break;
case:35:
alert("35");
break;
case:45:
alert("45");
break;
default:alert("other");
}
通过为每个case后面都添加一个break语句,就可以避免同时执行多个case代码的情况。加入确实需要混合几种情形,不要忘了在代码中添加注释,说明你是有意忽略了break关键字。如下:
switch(i){
case 25: //合并两种情形
case:35:
alert("25 or 35");
break;
case:45:
alert("45");
break;
default:alert("other");
}
switch语句可以使用任何数据类型,无论是字符串,还是对象都没有问题。其次,每个case的值不一定是常量,可以是变量,甚至是表达式。请看下面的例子:switch("hello world"){
case "hello" + " world": //hello world hello和world之间的空格也要输进去
alert("hello");
break;
case "goodbye":
alert("goodbye");
break;
default:
alert("other");
}
在这个例子中,switch语句使用的就是字符串。其中,第一种情形实际上是一个对字符串拼接操作求值的表达式。由于这个字符串拼接表达式的结果与switch的参数相等,因此结果就会显示“hello”。而且使用表达式作为case值还可以实现下列操作:
var num=25;
switch(true){
case num<0 :
alert("less than 0");
break;
case num>0 && num < 10:
alert("between 0 and 10");
break;
case num>10 && num<=20;
alert("between 10 and 20");
break;
default:alert("more than 20"); //结果为default
}
这个例子首先在switch语句外声明了变量num。而之所以给switch语句传递表达式true,是因为每个case值都可以返回一个布尔值。这样,每个case按照顺序被求值,知道找到匹配的值或者遇到default语句为止。
3.27 函数
函数对任何语言来说都是一个核心的概念。通过函数可以封装任意多条语句,而且可以在任何地方任何时候调用执行。ECMAScript中的函数使用function关键字来声明,后跟一组参数以及函数体。函数的基本语法如下所示:
function functionName(arg0,arg1,...argN){
statements
}
以下是一个函数示例:
function sayHi(name, message){
alert("hello "+name+","+message;
}
这个函数可以通过其函数名来调用,后面还要加上一对圆括号和参数(圆括号中的参数如果有多个,可以用逗号隔开)。调用sayHi()函数的代码如下:
sayHi("lilei","how are you");
这个函数输出结果为“hello lilei, how are you”。函数中定义的命名参数name和message被用作了字符串拼接的两个操作数,而结果最终通过警告框显示了出来。
ECMAScript中的函数在定义时不必指定是否返回值。实际上,任何函数在任何时候都可以通过return 语句后跟要返回的值来实现返回值。请看下面的例子:
function sum(num1.num2){
return num1+num2;
}
这个sum()函数的作用是把两个值加起来返回一个结果。我们注意到,除了return语句之外,没有任何声明表示该函数会返回一个值。调用这个函数的示例代码如下:
var result= sum(5,10);
这个函数会在执行完return语句之后停止并立即退出。因此位于return语句之后的任何代码都不会执行。
如:
function sum(num1.num2){
return num1+num2;
alert("hello"); //永远不会弹出
}
当然,一个函数也可以包含多个return语句,如下:
function diff(num1,num2){
if(num1<num2){
return num2-num1;
}else{
return num1-num2;
}
}
这个例子中定义的diff()函数用于计算两个数值的差。如果第一个数比第二个小,则调用第二个数减第一个数;否则,用第一个数减第二个数。代码中的两个分支都焗油自己的return语句,分别用于执行正确的计算。
另外,return语句也可以不带要任何返回值。在这种情况下,函数在停止执行后将返回undefined值。这种用法一般用在需要提前停止函数执行而又不需要返回值的情况下。如下:
function sayHi(name, message){
reutrn;
alert("hello "+name+","+message); //不会执行
}
推荐的做法是要么让函数始终都返回一个值,要么永远都不要返回值。否则,如果函数有时候返回值,有时候有不返回值,会给调试代码带来不便。
严格模式下对函数有一些限制:
不能把函数命名为eval 或 arguments;
不能把参数命名为eval 或 arguments;
不能出现两个命名参数同名的请。
如果发生以上情况,就会导致语法错误,代码无法执行。
3.27.1 理解参数
ECMAScript函数的参数与大多数其他语言中函数的参数有所不同。ECMAScript函数不介意传递进来多少个参数,也不在乎传进来参数是什么数据类型。也就是说,即便你定义的函数只接收两个参数,在调用这个函数时也未必一定要传递两个参数。可以传递一个、三个甚至不传递参数,而解析器永远不会有什么怨言。之所以会这样,原因是ECMAScript中的参数在内部是用一个数组来表示的。函数接收到的始终都是这个数组,而不关心数组中包含哪些参数(如果有参数的话)。在函数体内可以通过arguments对象来访问这个参数数组,从而获取传递给函数的每一个参数。
其实,arguments对象只是与数组类似(它并不是array的实例),因为可以使用方括号语法访问它的每一个元素(即第一个元素是arguments[0],第二个元素是arguments[1],以此类推),使用length属性来确定传递进来多少个参数。在前面的例子中,sayHi()函数的第一个参数的名字叫name,而该参数的值也可以通关访问arguments[0]来获取。因此,那个函数也可以像下面这样重写,即不显式地使用命名参数:
function sayHi(){
alert("hello "+arguments[0]+","+arguments[1]);
}
这个重写后的函数中不包含命名的参数。虽然没有使用name和message标识符,但函数的功能依旧。这个事实说明了ECMAScript函数的一个重要特点:命名的参数只提供便利,但不是必需的。
通过访问arguments对象的length属性可以获知有多少个参数传递给了函数。下面这个函数会在每次被调用时,输出传入其中的参数个数:
function howManyArgs(){
alert(arguments.length);
}
howMnayArgs("string",45); //2
howMnayArgs(); //0
howMnayArgs(45); //1
执行以上代码会依次出现3个警告框,分别显示2、0和1。由此可见,开发人员可以利用这一点让函数能够接受任意个参数并分别实现适当的功能。如下:
function doAdd(){
if(arguments.length==1){
alert(arguments[0]+10);
}else if(arguments.length==2){
alert(arguments[0]+arguments[1]);
}
}
doAdd(10); //20
doAdd(30,20); //50
函数doAdd()会在只有一个参数的情况下给该参数加上10;如果是两个参数,则将那个参数简单相加并返回结果。因此,doAdd(10)会返回20,而doAdd(30,20)则会返回50。
另一个与参数相关的重要方面,就是arguments对象可以与命名参数一起使用,如下:
function doAdd(num1,num2){
if(arguments.length==1){
alert(num1+10);
}else if(argument.length==2){
alert(arguments[0]+num2);
}
}
在重写后的这个doAdd()函数中,两个命名参数都与arguments对象一起使用。由于num1的值与arguments[0]的值相同,因此它们可以互换使用(当然,num2和arguments[1]的值也是如此)。
关于arguments的行为,还有一点比较有意思。那就算它的值用于与对应命名参数的值保持同步。如:
function doAdd(num1,num2){
arguments[1]=10;
alert(arguments[0]+num2);
}
每次执行这个doAdd()函数都会重写第二个参数,将第二个参数的值修改为10。因为arguments对象中的值会自动反映到对应的命名参数,所以修改arguments[1],也就是修改num2,结果它们的值都会变成10。不过,这并不是说读取这两个值会访问相同的内存空间;它们的内存空间是独立的,但它们的值会同步。另外还要记住,如果只传入了一个参数,那么为arguments[1]设置的值不会反映到命名参数中。这是因为arguments对象的长度是由传入的参数个数决定的,不是由定义函数时的命名参数的个数决定的。
关于参数还要记住最后一点:没有传递值的命名参数将自动被赋予undefined值。这就跟定义了变量但又没有初始化一样。例如,如果只给doAdd()函数传递了一个参数,则num2中就会保存undefined值。
严格模式对如何使用arguments对象做出了一些限制。首先,像前面例子中那样的复制会变得无效。也就是说,即使把arguments[1]设置为10,num2的值仍然还是undefined。其次,重写arguments的值会导致语法错误(代码将不会执行)。ECMAScript中的所有参数传递的都是值,不可能通过引用传递参数。
3.27.2 没有重载
ECMAScript函数不能像传统意义上那样实现重载。
如果在ECMAScript中定义了两个名字相同的函数,则该名字只属于后定义的函数。如下:
function addSomeNum(num){
return num+100;
}
function addSomeNum(num){
return num+200;
}
var result= addSomeNum(100); //300在此,函数addSomeNum()被定义了两次。第一个版本给参数加100,而第二个版本给参数加200。由于后定义的函数覆盖了先定义的函数,因此当在最后一行代码中调用这个函数时,返回的结果就是300。
如前所述,通过检查传入函数中参数的类型和数量并做出不同的反应,可以模仿方法的重载。
3.28 小结
ECMAScript中的基本数据类型包括 Undefined、Null、Boolean、Number和String。
与其他语言不同,ECMAScript没有为整数和浮点数值分别定义不同的数据类型,Number类型可用于表示所有数值。
ECMAScript中也有一种复杂的数据类型,即Object类型,该类型是这门语言中所有对象的基础类型。
严格模式为这门语言中容易出错的地方施加了限制。
ECMAScript提供了很多与C及其他类C语言中相同的基本操作符,包括算术操作符、布尔操作符、关系操作符、相等操作符及赋值操作符等。
ECMAScript从其他语言中借鉴了很多流控制语句,例如if语句、for语句和switch语句等。