Chapter02 词法结构
1.可省略的分号
如果当前语句无法和下一行语句合并解析,则js解析器会在当前行后填补分号:
var a
a
=
3
console.log(a)
会被解析成:var a; a=3; console.log(a);
var y = x+f
(a+b).toString()
会被解析成: var y = x + f(a+b).toString(); 而不是 var y = x + f; (a+b).toString();
一般情况下,如果一条语句以(,[,/,+,-开始,那么它极有可能和前一条语句合在一起解析。所以一个保守的方法就是在语句前加一个分号,这样哪怕之前的语句被修改了,分号被误删了,当前语句还是可以正确地解析。
但填补分号有两个例外,第一个是return, break和continue,如果这三个关键字后面跟着换行,js引擎会在换行处填补分号,即
return
true
会被解析成 return; true;
第二个是++, --运算符,这些运算符可以作为表达式的前缀,也可以作为后缀,但如果作为后缀,它和表达式应该在同一行,否则,行尾将填补分号,同时++,--
会作为下一行的前缀操作符并与之一起解析,例如:
y
++
x
会被解析成 y; ++x;
Chapter03 类型、值和变量
1.反斜杠“\”
i.ECMAScript3要求字符串直接量必须在一行,而ECMAScript5允许在多行,每行末尾以\结束。
ii.除了上面这种情况,如果\出现在一个非转义的字符之前,则\将被忽略,如\#与#等价。
2.Falsy Value:
undefined null 0 -0 NaN ""
3.Truthy Value:
All values except for the falsy values above. (All objects and arrays will be converted to true when a boolean value is needed.)
4.null & undefined
当对null进行typeof运算时,得到的是“object”,也就是说,可以将null当为一个特殊的对象,含义是“非对象”。但实际上,通常认为null是它自有类型的唯一一个成员,它可以表示数字、字符或对象是“无值”的。
undefined用来表示更深层次的“空值”,它是变量的一种取值,表示未被初始化,如果对象属性或数组元素的值为undefined,则表示此属性或数组元素不存在。如果函数不返回任何值,则返回undefined,.引用没有提供实参的函数形参的值也会得到undefined.
区别:undefined是预定义的全局变量,但不是关键字,而null是关键字。
5.包装对象
如果程序中引用了字符串直接量,数字直接量,布尔直接量(true|false)的属性或方法,则js引擎会隐式创建一个与之对应的包装对象,分别是String,Number,Boolean,然后访问该对象的相应属性或方法,一旦引用过后,该包装对象即被销毁(虽然实现上并不一定创建或销毁这个临时对象,然而整个过程看起来是这样的)。
null和undefined没有包装对象,所以试图引用它们的属性会引发一个error.
看如下代码,思考原因:
var s = "hello kitty";
s.len = 3;
var t = s.len; //undefined
上面的代码,第二行创建了一个临时对象,并为该对象添加一个属性len,随后这个对象被销毁。在第三行试图访问s的len属性时,由于该临时对象已不存在,访问的字符直接量的len属性,所以会是undefined.
可以通过构造方法显示地创建包装对象:
var s = "str",i=1,b=true;
var S = new String(s),
I = new Number(i),
B = new Boolean(b);
js引擎会在必要时将包装对象转换为原始值,所以包装对象常常————但不总是————表示得和原始值一样。==运算符将包装对象和原始值视为相等,但===全等运算符视它们为不等。typeof s返回“string”,但typeof S返回“object”.
6.原始值和对象引用
js中,原始值比较的是值,而对象比较的是引用,两个对象只有引用的是同一个基对象时,其值才相等,例:
var x = {p:1}, y = {p:1};
x == y; // =>false: 两个单独的对象永不相等
var a = [], b = [];
a == b; //=>false: 两个单独的数组永不相等
如果想比较对象的内容是否相等,需要自定义一个比较方法:
function equalArray(a,b) {
if(a.length != b.length) {
return false;
}
for(int i = 0; i < a.length; i++) {
if(a[i] != b[i]) {
return false;
}
}
return true;
}
7.类型转换
7.1转换和相等性
l NaN和任何值都不等,包括它本身,即NaN == NaN //=>false.
l 对象除了和它自身相等外,和其它任何值都不等:
var o = new Object(),o2 = new Object();
o == o2; //=>false
o == o; //=>true
l 一个值转换为另一个值并不意味着这两个值相等。例如,在期望使用布尔值的地方undefined被转换为false,但并不表明undefined == false.js运算符和语句期望使用多样化的数据类型,并可以相互转换,但==运算符从不试图将其操作数转换为布尔值。
Number(),Boolean(),String(),当不通过new运算符调用时,它们会作为类型转换函数执行。如果通过Number()传入一个字符串,
它会试图将其转换为一个整数或浮点数直接量,注意这个方法只能基于10进制进行转换,而不能出现非法的尾随字符。
parseInt()和parseFloat()更灵活:parseInt()只解析整数,parseFloat()解析整数和浮点数。
parseInt()和parseFloat()都会跳过任意数量的前导空格,并忽略非法的尾随字符以尽可能多地解析数字字符,例如parseInt(' 323dksfds')会被解析为整数323.
如果第一个非空格字符是一个非法的数字直接量,将直接返回NaN.
如果字符的前缀是0x或0X,parseInt()将其解析为16进制数;在ECMAScript3中,parseInt()可以对前缀为0(不能是0x或0X)的数字做8进制转换,
但由于细节没有详细说明,所以无法直接使用parseInt()来对前缀为0的值进行解析,除非你明确指出所使用的转换基数!在ECMAScript5中,parseInt()只有在明确传入第二个参数8时才会解析8进制数。(但是经我测试,所有浏览器,包括IE7,IE6我没测,都可以解析parse(023),输出均为19,
所以感觉书中这里说的没什么用,不过当然,明确指出基数是一个好习惯。另外,所有浏览器测试均表明parseInt(023)和parseInt('023')的结果一致,也就是说,参数是不是一个字符串都可以,但是前者应该是直接按数字去处理的,后者是先转换为数字再处理,看下面parseInt(.1)和parseInt('.1')的例子就会明白):
parseInt(.1) //=>0
parseInt('.1') //=> NaN
parseInt("-23.323xxx") //=>-23
parseFloat('$323.22') //=> NaN
parseFloat(' 3.12 meters') //=> 3.14
parseInt('0XFF') //=>255
parseInt('0xff') //=>255
parseInt('0xFf') //=>255
parseInt('11',2) //=>3
parseInt(11,2) //=>3
parseInt('zz',36) //=>1295 (36*35+35)
parseInt('zz',36) //=>error: zz is not defined
parseInt(32,4) //=>14
parseInt(32,5) //=>17
7.2.对象转换为原始值
注:这里说的转换规则只适用于本地对象, 宿主对象(例如由浏览器定义的对象)根据各自的算法可以转换成字符和数字。
所有对象都继承了两个方法:toString()和valueOf():
toString(): Object的toString()方法默认返回"[object object]",Array,RegExp,Function,Date重写了此方法:
Array