数据类型

ECMAscript中有五种简单数据类型Undefined,Null,Boolean,Number,String

还有一种复杂数据类型Object。

typeof操作符

typeof可能返回下列某个字符串

undefined--------------如果这个值未定义

boolean----------------如果这个值是布尔值

string------------------如果这个值是字符串

number----------------如果这个值是数值

object-----------------如果这个值是对象或者null

function---------------如果这个值是函数

Undefined类型

Undefined类型只有一个值,即undefined。在使用var声明变量但没有初始化时这个变量的值就是undefined。

当使用typeof对未定义的变量操作时,返回也是undefined。

Null类型

Null类型只有一个值就是null,它表示一个空对象指针。

所以说一个新定义的变量如果要用于存放对象,那么就初始化为null。

undefined值派生自null值,若判定undefined是否和null相等,则会返回true。

Boolean类型

Boolean类型有两个值,true和false。

Number类型

Number类型的值可以是十进制数字,也可以是八进制的数字,八进制的值的第一位必须是零(0),也可以是十六进制的数字,十六进制值的前两位必须是0x,后面跟的字母A-F可以大写也可以小写。

浮点数,在计算时浮点数可能会被转换为整数,对于极大或者极小的数字可以使用e表示法。

  1. var floatNum = 3.125e7;
  2. var floatNum2 = 3.125E7;

数值范围,ECMAscript能够表示的最小数和最大数保存在Number.MIN_VALUE和Number.MAX_VALUE中,每个浏览器不一样。如果某一次计算超过了数值范围,那么会被转换为特殊的Infinity值,如果是负数,会是-Infinity(负无穷),如果是正数,会是Infinity(正无穷)。

Infinity是不能参与计算的值,要想确定一个值是不是有穷的,可以使用isFinite()函数,如果参数是最大值和最小值之间,那么这个函数会返回true。

NaN,即非数值(Not a Number),如果计算本要返回数值却未返回数值,那么就会返回NaN。

NaN有两个特点,第一个是涉及NaN的操作都会返回NaN,第二个是NaN与任何值都不相等,包括它本身。

函数isNaN()可以帮我们判断是否一个参数是NaN,如果一个参数是数字,就会返回false,如果一个参数不能被转换为数字,就会返回true。

数值转换,有三个函数可以把非数字转换为数字:Number(),parseInt(),parseFloat()。Number()用语任何类型数据类型转换,后两个专门转换字符串。

Number()转换的规则:

如果是Boolean值,true和false分别被转换为1和0。

如果是数字值,直接传入和返回。

如果是null值,返回0。

如果是undefined值,返回0。

如果是字符串,就按照很复杂的规则转换:

如果只含有数字,直接转换为数字,会忽略前面的0;

如果字符串中含有有效的小数点,则转换为浮点数;

如果有有效的十六进制格式,就按照十六进制转换;

如果字符串是空的,就转换为0;

如果含有上述格式之外的字符,就转换为NaN。

如果是对象,则调用对象的valueOf()方法,然后依找前面的规则转换。如果转换结果是NaN,则调用对象的toString()方法,然后再按照前面的规则转换。

parseInt()的转换规则:从第一个字符往后一个一个解析,如果第一个字符不是数字或者符号,就返回NaN,知道解析完所有数值或者遇到非数字字符。22.5会被转换为22,因为小数点不是有效数字字符。在转换八进制和十六进制数字时,不同ECMAscript版本情况不同,所以可以有第二个参数指定用什么进制来转换数值。

parsefloat()的转换规则:跟parseInt()一样,从前往后解析,直到遇到无效的浮点数字符。

String类型

转义字符

字符串的长度可以通过length属性获得。

字符串不可变,一旦字符串创建,就不能在改变了,改变某个变量保存的字符串,首先要销毁原来的字符串,然后在用另一个新的字符串填充该变量。

转换为字符串:把其他值转换为字符串,有两种方法,第一种是几乎每种值都有的toString()方法。数值,布尔值,对象和字符串值都有toString()方法。但是null和undefined没有这个方法。如果不知道要转换的值是不是null或者undefined,就使用第二种方法,使用转型函数String(),这个能将任何类型的值转换为字符串。

string()的转换规则:

如果值有toString()方法,就调用toString()方法;

如果值是null,就返回字符串"null";

如果值是undefined,就返回字符串"undefined"。

Object类型

ECMAscript中对象是一组数据和功能的集合,可以用new后跟对象类型创建。

操作符

一元操作符

递增递减操作符,即++和--。他们可以放在变量的前面或者后面,区别是放在前面是先递增或递减操作然后语句求值,放在后面语句先求值再递增或递减。

当应用于不同值时,递增和递减的规则:

当应用于包含有效数字的字符串时,先将其转换为数字,然后再进行加减1的操作;

当字符串不包含有效数字,将变量变为NaN;

当应用于布尔值false和true时,现将其转变为0和1再进行加减1;

当应用于浮点数时,直接加减1;

当应用于对象时,先调用valueOf()方法获得一个值,然后使用前面的规则,如果结果是NaN,再调用toString()方法后再应用前面的规则。

一元加和减操作符,即+和-。主要用于数值运算,但是对非数值使用+操作符时会转变变量的类型,布尔值false和true将被转换为0和1,字符串值会被按照一组特殊的规则进行解析,而对象是先调用它们的valueOf()和(或)toString()方法,再转换得到的值。对数值使用-时,会变成负数,对非数值使用时,和+转换规则一样,然后再将结果变为负数。

位操作符

对于有符号的整数,32位中的前31位用于表示整数的值。第32位用于表示数值的符号:0表示正数,1表示负数。这个表示符号的位叫做符号位,符号位的值决定了其他位数值的格式。其中,正数以纯二进制格式存储31位中的每一位都表示2的幂。

负数同样以二进制码存储,但使用的格式是二进制补码。计算一个数值的二进制补码,需要经过下列3个步骤:

(1) 求这个数值绝对值的二进制码(例如,要求18 的二进制补码,先求 18 的二进制码);
(2) 求二进制反码,即将 0 替换为 1,将 1 替换为 0;
(3) 得到的二进制反码加 1。

在ECMAscript中,当对数值应用位操作符时,后台会发生如下转换过程:64位的数值被转换成32位数值,然后执行位操作,最后再将32位的结果转换回64位数值。但这个转换过程也导致了一个严重的副效应,即在对特殊的 NaN 和 Infinity 值应用位操作时,这两个值都会被当成 0 来处理。

如果对非数值使用位操作符,会先使用Number()使其变成数字然后才进行操作。

按位非(NOT)

按位非操作符由波浪线表示~,执行按位非的结果就是返回数值的反码。

按位非操作的本质其实是:操作数的负值减1。

由于按位非是在数值表示的最底层执行操作,因此速度比变负值再减1更快。

按位与(AND)

按位与由&符号表示,它有两个操作数,就是将两个数值的每一位对齐,对应位都是1时才返回1,任何一位是0,结果都是0。

按位或(OR)

按位或由竖线|表示,它也有两个操作数,就是将两个数值的每一位对齐,有一个位是1的情况下就返回 1,而只有在两个位都是0的情况下才返回0。

按位异或(XOR)

按位异或由插入符号^表示,它也有两个操作数,两个数值对应位上只有一个1时才返回1,如果对应的两位都是1或都是0,则返回0。

左移(<<)

左移操作符由两个小于号(<<)表示,这个操作符会将数值的所有位向左移动指定的位数,空出的位置用0补齐。左移不会影响操作数的符号位。

有符号的右移(>>)

右移操作符由两个大于号(>>)表示,这个操作符会将数值向右移动,但保留符号位,会用符号位的值来填充所有空位。

无符号右移(>>>)

无符号右移操作符由3 个大于号(>>>)表示,这个操作符会将数值的所有32位都向右移动。对正数来说,无符号右移的结果与有符号右移相同,因为无符号右移是用0来填充空位。但是负数就不一样了,会把负数变成正数,并且变得很大。

布尔操作符

逻辑非(!)

逻辑非操作符首先会将它的操作数转换为一个布尔值,然后再对其求反。

它遵循以下规则:

如果操作数是一个对象,返回false;对象==true
如果操作数是一个空字符串,返回true;空字符串==false
如果操作数是一个非空字符串,返回false;非空字符串==true
如果操作数是数值0,返回true;0==false
如果操作数是任意非0 数值(包括Infinity),返回false;非0数值==true
如果操作数是null,返回true;null==false
如果操作数是NaN,返回true;NaN==false
如果操作数是undefined,返回true。undefined==false

逻辑与(&&)

在有一个操作数不是布尔值的情况下,逻辑与操作就不一定返回布尔值。此时,它遵循下列规则:

如果第一个操作数是对象,则返回第二个操作数;
如果第二个操作数是对象,则只有在第一个操作数的求值结果为true 的情况下才会返回该对象;
如果两个操作数都是对象,则返回第二个操作数;
如果有一个操作数是null,则返回null;
如果有一个操作数是NaN,则返回NaN;
如果有一个操作数是undefined,则返回undefined。

逻辑与操作属于短路操作,如果第一个操作数是false,则无论第二个操作数是什么值,结果都不再可能是true 了。

逻辑或(||)

与逻辑与操作相似,如果有一个操作数不是布尔值,逻辑或也不一定返回布尔值。此时,它遵循下列规则:
如果第一个操作数是对象,则返回第一个操作数;
如果第一个操作数的求值结果为false,则返回第二个操作数;
如果两个操作数都是对象,则返回第一个操作数;
如果两个操作数都是null,则返回null;
如果两个操作数都是NaN,则返回NaN;
如果两个操作数都是undefined,则返回undefined。
与逻辑与操作符相似,逻辑或操作符也是短路操作符。也就是说,如果第一个操作数的求值结果为true,就不会对第二个操作数求值了。

乘性操作符

乘法(*)

在处理特殊值的情况下,乘法操作符遵循下列特殊的规则:
如果操作数都是数值,执行常规的乘法计算,即两个正数或两个负数相乘的结果还是正数,而如果只有一个操作数有符号,那么结果就是负数。如果乘积超过了ECMAScript 数值的表示范围,则返回Infinity 或-Infinity;
如果有一个操作数是NaN,则结果是NaN;
如果是Infinity 与0 相乘,则结果是NaN;
如果是Infinity 与非0 数值相乘,则结果是Infinity 或-Infinity,取决于有符号操作数的符号;
如果是Infinity 与Infinity 相乘,则结果是Infinity;
如果有一个操作数不是数值,则在后台调用Number()将其转换为数值,然后再应用上面的规则。

除法(/)

与乘法操作符类似,除法操作符对特殊的值也有特殊的处理规则。这些规则如下:
如果操作数都是数值,执行常规的除法计算,即两个正数或两个负数相除的结果还是正数,而如果只有一个操作数有符号,那么结果就是负数。如果商超过了ECMAScript 数值的表示范围,则返回Infinity 或-Infinity;
如果有一个操作数是NaN,则结果是NaN;
如果是Infinity 被Infinity 除,则结果是NaN;
如果是零被零除,则结果是NaN;
如果是非零的有限数被零除,则结果是Infinity 或-Infinity,取决于有符号操作数的符号;
如果是Infinity 被任何非零数值除,则结果是Infinity 或-Infinity,取决于有符号操作数的符号;
如果有一个操作数不是数值,则在后台调用Number()将其转换为数值,然后再应用上面的规则。

求模(%)

与另外两个乘性操作符类似,求模操作符会遵循下列特殊规则来处理特殊的值:
如果操作数都是数值,执行常规的除法计算,返回除得的余数;
如果被除数是无穷大值而除数是有限大的数值,则结果是NaN;
如果被除数是有限大的数值而除数是零,则结果是NaN;
如果是Infinity 被Infinity 除,则结果是NaN;
如果被除数是有限大的数值而除数是无穷大的数值,则结果是被除数;
如果被除数是零,则结果是零;
如果有一个操作数不是数值,则在后台调用Number()将其转换为数值,然后再应用上面的规则。

加性操作符

加法(+)

如果两个操作符都是数值,执行常规的加法计算,然后根据下列规则返回结果:
如果有一个操作数是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"。

减法(-)

同样需要遵循一些特殊规则,如下所示:
如果两个操作符都是数值,则执行常规的算术减法操作并返回结果;
如果有一个操作数是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()方法并将得到的字符串转换为数值。

关系操作符

小于(<)、大于(>)、小于等于(<=)和大于等于(>=)这几个关系操作符用于对两个值进行比较。

当关系操作符的操作数使用了非数值时,也要进行数据转换或完成某些奇怪的操作。以下就是相应的规则。
如果两个操作数都是数值,则执行数值比较。
如果两个操作数都是字符串,则比较两个字符串对应的字符编码值。
如果一个操作数是数值,则将另一个操作数转换为一个数值,然后执行数值比较。
如果一个操作数是对象,则调用这个对象的valueOf()方法,用得到的结果按照前面的规则执行比较。如果对象没有valueOf()方法,则调用toString()方法,并用得到的结果根据前面的规则执行比较。
如果一个操作数是布尔值,则先将其转换为数值,然后再执行比较。

相等操作符

ECMAScript 的解决方案就是提供两组操作符:相等和不相等——先转换再比较,全等和不全等——仅比较而不转换。

相等和不相等(== !=)

在转换不同的数据类型时,相等和不相等操作符遵循下列基本规则:
如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值——false 转换为0,而true 转换为1;
如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值;
如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法,用得到的基本类型值按照前面的规则进行比较;

这两个操作符在进行比较时则要遵循下列规则。
null 和undefined 是相等的。
要比较相等性之前,不能将null 和undefined 转换成其他任何值。
如果有一个操作数是NaN,则相等操作符返回false,而不相等操作符返回true。重要提示:
即使两个操作数都是NaN,相等操作符也返回false;因为按照规则,NaN 不等于NaN。
如果两个操作数都是对象,则比较它们是不是同一个对象。如果两个操作数都指向同一个对象,则相等操作符返回true;否则,返回false。

全等和不全等(=== !==)

比较前不转换数据的类型,直接比较。

条件操作符

  1. variable = boolean_expression ? true_value : false_value;

赋值操作符

简单的赋值操作符由等于号(=)表示,其作用就是把右侧的值赋给左侧的变量。

每个主要算术操作符(以及个别的其他操作符)都有对应的复合赋值操作符。

乘/赋值(*=)
除/赋值(/=)
模/赋值(%=)
加/赋值(+=)
减/赋值(-=)
左移/赋值(<<=)
有符号右移/赋值(>>=)
无符号右移/赋值(>>>=)

逗号操作符

使用逗号操作符可以在一条语句中执行多个操作。

  1. var num1=1, num2=2, num3=3;

除此之外,逗号操作符还可以用于赋值。

  1. var num = (5, 1, 4, 8, 0); // num 的值为0

语句

if语句

  1. if (condition) statement1 else statement2
  2.  
  3. if (i > 25)
  4. alert("Greater than 25."); // 单行语句
  5. else {
  6. alert("Less than or equal to 25."); // 代码块中的语句
  7. }
  8.  
  9. if (condition1) statement1 else if (condition2) statement2 else statement3
  10.  
  11. if (i > 25) {
  12. alert("Greater than 25.");
  13. } else if (i < 0) {
  14. alert("Less than 0.");
  15. } else {
  16. alert("Between 0 and 25, inclusive.");
  17. }

do-while语句

  1. do {
  2. statement
  3. } while (expression);
  4.  
  5. var i = 0;
  6. do {
  7. i += 2;
  8. } while (i < 10);
  9. alert(i);

while语句

  1. while(expression) statement
  2.  
  3. var i = 0;
  4. while (i < 10) {
  5. i += 2;
  6. }

for语句

  1. for (initialization; expression; post-loop-expression) statement
  2.  
  3. var count = 10;
  4. for (var i = 0; i < count; i++){
  5. alert(i);
  6. }
  7.  
  8. var count = 10;
  9. for (var i = 0; i < count; i++){
  10. alert(i);
  11. }
  12. alert(i); //
  13.  
  14. for (;;) { // 无限循环
  15. doSomething();
  16. }

for-in语句

  1. for (property in expression) statement
  2.  
  3. for (var propName in window) {
  4. document.write(propName);
  5. }

如果表示要迭代的对象的变量值为null 或undefined,for-in 语句会抛出错误。ECMAScript 5 更正了这一行为;对这种情况不再抛出错误,而只是不执行循环体。为了保证最大限度的兼容性,建议在使用for-in 循环之前,先检测确认该对象的值不是null 或undefined。

label语句

使用label 语句可以在代码中添加标签,以便将来使用。

  1. label: statement
  2.  
  3. start: for (var i=0; i < count; i++) {
  4. alert(i);
  5. }

break和continue语句

break 和continue 语句用于在循环中精确地控制代码的执行。其中,break 语句会立即退出循环,强制继续执行循环后面的语句。而continue 语句虽然也是立即退出循环,但退出循环后会从循环的顶部继续执行。

break 和continue 语句都可以与label 语句联合使用,从而返回代码中特定的位置。这种联合使用的情况多发生在循环嵌套的情况下,如下面的例子所示:

  1. var num = 0;
  2. outermost:
  3. for (var i=0; i < 10; i++) {
  4.   for (var j=0; j < 10; j++) {
  5.     if (i == 5 && j == 5) {
  6.       break outermost;
  7.     }
  8.   num++;
  9.   }
  10. }
  11. alert(num); //
  1. var num = 0;
  2. outermost:
  3. for (var i=0; i < 10; i++) {
  4. for (var j=0; j < 10; j++) {
  5. if (i == 5 && j == 5) {
  6. continue outermost;
  7. }
  8. num++;
  9. }
  10. }
  11. alert(num); //

with语句

with 语句的作用是将代码的作用域设置到一个特定的对象中。

  1. with (expression) statement;

定义with 语句的目的主要是为了简化多次编写同一个对象的工作。

  1. var qs = location.search.substring(1);
  2. var hostName = location.hostname;
  3. var url = location.href;

上面几行代码都包含location 对象。如果使用with 语句,可以把上面的代码改写成如下

  1. with(location){
  2.   var qs = search.substring(1);
  3.   var hostName = hostname;
  4.   var url = href;
  5. }

这意味着在with 语句的代码块内部,每个变量首先被认为是一个局部变量,而如果在局部环境中找不到该变量的定义,就会查询location 对象中是否有同名的属性。如果发现了同名属性,则以location 对象属性的值作为变量的值。

严格模式下不允许使用with 语句,否则将视为语法错误。

由于大量使用with 语句会导致性能下降,同时也会给调试代码造成困难,因此在开发大型应用程序时,不建议使用with 语句。

switch语句

  1. switch (expression) {
  2.   case value: statement
  3.     break;
  4.   case value: statement
  5.     break;
  6.   case value: statement
  7.     break;
  8.   case value: statement
  9.     break;
  10.   default: statement
  11. }
  1. switch (i) {
  2. case 25:
  3. alert("25");
  4. break;
  5. case 35:
  6. alert("35");
  7. break;
  8. case 45:
  9. alert("45");
  10. break;
  11. default:
  12.   alert("Other");
  13. }

switch 语句中的每一种情形(case)的含义是:“如果表达式等于这个值(value),则执行后面的语句(statement)”。而break 关键字会导致代码执行流跳出switch 语句。如果省略break 关键字,就会导致执行完当前case 后,继续执行下一个case。最后的default 关键字则用于在表达式不匹配前面任何一种情形的时候,执行机动代码(因此,也相当于一个else 语句)。

  1. switch (i) {
  2.   case 25:
  3.   /* 合并两种情形 */
  4.   case 35:
  5.     alert("25 or 35");
  6.     break;
  7.   case 45:
  8.     alert("45");
  9.     break;
  10.   default:
  11.     alert("Other");
  12. }
  1. switch ("hello world") {
  2.   case "hello" + " world":
  3.     alert("Greeting was found.");
  4.     break;
  5.   case "goodbye":
  6.     alert("Closing was found.");
  7.     break;
  8.   default:
  9.     alert("Unexpected message was found.");
  10. }
  1. var num = 25;
  2. switch (true) {
  3.   case num < 0:
  4.     alert("Less than 0.");
  5.     break;
  6.   case num >= 0 && num <= 10:
  7.     alert("Between 0 and 10.");
  8.     break;
  9.   case num > 10 && num <= 20:
  10.     alert("Between 10 and 20.");
  11.     break;
  12.   default:
  13.     alert("More than 20.");
  14. }

switch 语句在比较值时使用的是全等操作符,因此不会发生类型转换(例如,字符串"10"不等于数值10)。

函数

  1. function functionName(arg0, arg1,...,argN) {
  2. statements
  3. }
  4.  
  5. function sayHi(name, message) {
  6. alert("Hello " + name + "," + message);
  7. }

return 语句也可以不带有任何返回值。在这种情况下,函数在停止执行后将返回undefined值。

理解参数

ECMAScript 函数不介意传递进来多少个参数,也不在乎传进来参数是什么数据类型。也就是说,即便你定义的函数只接收两个参数,在调用这个函数时也未必一定要传递两个参数。可以传递一个、三个甚至不传递参数,而解析器永远不会有什么怨言。之所以会这样,原因是ECMAScript 中的参数在内部是用一个数组来表示的。函数接收到的始终都是这个数组,而不关心数组中包含哪些参数(如果有参数的话)。如果这个数组中不包含任何元素,无所谓;如果包含多个元素,也没有问题。实际上,在函数体内可以通过arguments 对象来访问这个参数数组,从而获取传递给函数的每一个参数。

arguments 对象只是与数组类似(它并不是Array 的实例),因为可以使用方括号语法访问它的每一个元素,使用length 属性来确定传递进来多少个参数。

这个事实说明了ECMAScript 函数的一个重要特点:命名的参数只提供便利,但不是必需的。

关于arguments 的行为,还有一点比较有意思。那就是它的值永远与对应命名参数的值保持同步。

  1. function doAdd(num1, num2) {
  2. arguments[1] = 10;
  3. alert(arguments[0] + num2);
  4. }

每次执行这个doAdd()函数都会重写第二个参数,将第二个参数的值修改为10。因为arguments对象中的值会自动反映到对应的命名参数,所以修改arguments[1],也就修改了num2,结果它们的值都会变成10。不过,这并不是说读取这两个值会访问相同的内存空间;它们的内存空间是独立的,但它们的值会同步。另外还要记住,如果只传入了一个参数,那么为arguments[1]设置的值不会反应到命名参数中。这是因为arguments 对象的长度是由传入的参数个数决定的,不是由定义函数时的命名参数的个数决定的。

关于参数还要记住最后一点:没有传递值的命名参数将自动被赋予undefined 值。这就跟定义了变量但又没有初始化一样。

没有重载

通过检查传入函数中参数的类型和数量并作出不同的反应,可以模仿方法的重载。

函数参数传递

很多人认为 JS 中参数有两种传递方式:数字、字符串等按值传递;数组、对象等按地址(引用)传递。其实都是一种值传递。

  1. var v1 = []
  2. var v2 = {};
  3. var v3 = {};
  4. function foo(v1, v2, v3)
  5. {
  6. v1 = [1];
  7. v2 = [2];
  8. v3 = {a:3}
  9. }
  10.  
  11. foo(v1, v2, v3);
  12. alert (v1); // 空白
  13. alert (v2); // [object Object]
  14. alert (v3.a); // undefined

由此可见:v1、v2、v3 都没有被改变,v1 仍然是零个元素的数组,v2、v3 仍然是空白的对象。

但是,数组、对象等按值传递,是指变量地址的值。

数组、对象等的按值传递与数字、字符串还是有所不同的。数字、字符串是把值直接复制进去了,而数组、对象是把变量地址复制进去的。

前面我们让 v1、v2、v3 作为参数进入函数后,就有了地址副本,这些地址副本的指向和外面的 v1、v2、v3 的地址指向是相同的。但我们为 v1、v2、v3 赋了值,也就是说我们把地址副本的指向改变了,指向了新的数组和对象。这样内部的 v1、v2、v3 和外部的 v1、v2、v3 就完全断了。

如果我们不赋新值,而是直接操作它,那么,它操作到的,仍然是和外面的 v1、v2、v3 指向的同一块数组或对象。

  1. var v1 = []
  2. var v2 = {};
  3. var v3 = {a:0};
  4. function foo(v1, v2, v3)
  5. {
  6. v1.push (1);
  7. v2.a = 2;
  8. v3.a = 3;
  9. }
  10.  
  11. foo(v1, v2, v3);
  12. alert (v1); // 1
  13. alert (v2.a); // 2
  14. alert (v3.a); //

js高级程序设计(三)基本概念的更多相关文章

  1. 读书笔记 - js高级程序设计 - 第十五章 使用Canvas绘图

    读书笔记 - js高级程序设计 - 第十三章 事件   canvas 具备绘图能力的2D上下文 及文本API 很多浏览器对WebGL的3D上下文支持还不够好   有时候即使浏览器支持,操作系统如果缺缺 ...

  2. js高级程序设计笔记之-addEventListener()与removeEventListener(),事件解除与绑定

    js高级程序设计笔记之-addEventListener()与removeEventListener(),事件解除与绑定 addEventListener()与removeEventListener( ...

  3. 《JS高级程序设计》笔记 —— 解析查询字符串

    今天在继续翻阅<JS高级程序设计>的时候,正好翻到location对象这一小节,其中有一部分就是讲的解析查询字符串.看到这个内容立马想到了做去哪儿秋招笔试题的时候有这么一道题. 去哪儿笔试 ...

  4. angular.js高级程序设计书本开头配置环境出错,谁能给解答一下

    server.jsvar connect=require('connect');serveStatic=require('serve-static');var app=connect();app.us ...

  5. 《JavaScript高级程序设计》 -- 基本概念(一)

    之前看过好几遍<JavaScript高级程序设计>这一书,但是始终没有完完整整的看过一遍.从现在开始我会把它完整的啃一遍,每章节都记录笔记,自己的心得,加油! 由于前三章的内容比较简单,因 ...

  6. JS高级程序设计拾遗

    <JavaScript高级程序设计(第三版)>反反复复看了好多遍了,这次复习作为2017年上半年的最后一次,将所有模糊的.记不清的地方记录下来,方便以后巩固. 0. <script& ...

  7. JS高级程序设计学习笔记之第三章基本概念(语法,数据类型,流控制语句,函数)——查漏补缺

    一.语法: 区分大小写; 2.标识符:就是指变量.函数.属性的名字,或者函数的参数 a.标志符的规则:①第一个字符必须是一个字母.下划线(_)或一个美元符号($).                   ...

  8. JS高级程序设计第三版——基本概念

    前言:任何语言的核心都必然会描述这门语言最基本的工作原理.而描述的内容通常都要设计这门语言的语法.操作符.数据类型.内置功能等用于构建复杂解决方案的基本概念. 语法: 1.  区分大小写: 2.  标 ...

  9. 读书笔记 - js高级程序设计 - 第三章 基本概念

    启用严格模式 "use strict" 这是一个 pragma 编译指示 让编码意图更清晰  是一个重要原则 5种简单数据类型 Undefined Null Boolean Num ...

随机推荐

  1. spring+mybatis事务管理

    spring+mybatis事务管理 最近在和朋友做一个项目,考虑用springmvc+mybatis来做,之前在公司工作吧,对于数据库这块的配置也有人再弄,最近因为这个项目,我就上网学习了一些关于数 ...

  2. HDU 5670 Machine

    Machine Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

  3. 创建FrameWork

    1, http://blog.sina.com.cn/s/blog_407fb5bc01013v6s.html] 2,使用动态库 http://www.cocoachina.com/industry/ ...

  4. BZOJ 3159决战

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3159 题意:给出一棵树,(1)路径加一个值:(2)路径上的节点的值反转(只是值反转,不是节 ...

  5. eclipse+tomcat开发web项目

    也许正在使用的人会觉得这个过程谁不知道啊? 但是对于一个混迹各种语言编程有些年头的我来讲,却必须记录下来! 因为今天以前,我都通过配置[eclipse的tomcat插件]+编写[ant脚本,build ...

  6. Lambda表达式之Python

    一.lambda函数 1.lambda函数基础: lambda函数也叫匿名函数,即,函数没有具体的名称,而用def创建的方法是有名称的.如下: """命名的foo函数&q ...

  7. 【原创】pads2007 Layout 电气连接性检查过孔显示错误

    如图所示的电源铜皮过孔,勾选stiching选项,连接性检查会报错误: 去掉stiching选项,连接错误消失.

  8. C#计算某一些任务的执行时间(消耗时间)

    class Program { static void Main(string[] args) { System.Diagnostics.Stopwatch sw = new System.Diagn ...

  9. 未能加载文件或程序集xxx或它的某一个依赖项 试图加载格式不正确的程序

    解决方案:IIS——应用程序池——高级设置——启用32位应用程序 :true.

  10. HTML笔记(七)head相关元素<base> & <meta>

    <head>元素是所有头部元素的容器. 可添加的标签有:<title>.<base>.<link>.<meta>.<script> ...