读《JavaScript权威指南》笔记(一)
1.Number() parseInt() parseFloat()
如果通过Number()转换函数传入一个字符串,它会试图将其转换为一个整数或浮点数直接量,这个方法只能基于十进制数进行转换,并且不能出现非法的尾随字符。parseInt()函数和parseFloat()函数(它们是全局函数,不从属于任何类的方法)更加灵活。parseInt()只解析整数,而parseFloat()则可以解析整数和浮点数。如果字符串前缀是“0x”或者“0X”,parseInt()将其解释为十六进制数[插图],parseInt()和parseFloat()都会跳过任意数量的前导空格,尽可能解析更多数值字符,并忽略后面的内容。如果第一个非空格字符是非法的数字直接量,将最终返回NaN:
parseInt("3 blind mice") // => 3 parseFloat(" 3.14 meters") // => 3.14 parseInt("-12.34") // => -12 parseInt("0xFF") // => 255 parseInt("0xff") // => 255 parseInt("-0XFF") // => -255 parseFloat(".1") // => 0.1 parseInt("0.1") // => 0 parseInt(".1") // => NaN: 整数不能以"."开始 parseFloat("$72.47"); // => NaN: 数字不能以"$"开始
parseInt()可以接收第二个可选参数,这个参数指定数字转换的基数,合法的取值范围是2~36,例如:
parseInt("11", 2); // => 3(1*2 + 1) parseInt("ff", 16); // => 255(15*16 + 15) parseInt("zz", 36); // => 1295(35*36 + 35) parseInt("077", 8); // => 63(7*8 + 7) parseInt("077", 10); // => 77(7*10 + 7)
2. ++运算符
“++”运算符从不进行字符串连接操作,它总是会将操作数转换为数字并增1。如果x是字符串“1”,++x的结果就是数字2,而x+1是字符串“11”。
3. +运算符
加号的转换规则优先考虑字符串连接,如果其中一个操作数是字符串或者转换为字符串的对象,另外一个操作数将会转换为字符串,加法将进行字符串的连接操作。如果两个操作数都不是类字符串(string-like)的,那么都将进行算术加法运算。
从技术上讲,加法操作符的行为表现为:
·如果其中一个操作数是对象,则对象会遵循对象到原始值的转换规则转换为原始类值(参照3.8.3节):日期对象通过toString()方法执行转换,其他对象则通过
·在进行了对象到原始值的转换后,如果其中一个操作数是字符串的话,另一个操作数也会转换为字符串,然后进行字符串连接。
valueOf()方法执行转换(如果valueOf()方法返回一个原始值的话)。由于多数对象都不具备可用的valueOf()方法,因此它们会通过toString()方法来执行转换。
·否则,两个操作数都将转换为数字(或者NaN),然后进行加法操作。
这里有一些例子:
1 + 2 // => 3: 加法 "1" + "2" // => "12": 字符串连接 "1" + 2 // => "12": 数字转换为字符串后进行字符串连接 1 + {} // => "1[object Object]": 对象转换为字符串后进行字符串连接 true + true // => 2: 布尔值转换为数字后做加法 2 + null // => 2: null转换为0后做加法 2 + undefined// => NaN: undefined转换为NaN后做加法
4. 运算符从右到左的结合性
x = ~-y; w = x = y = z; q = a?b:c?d:e?f:g; //和下面这段代码一模一样: x = ~(-y); w =(x =(y = z)); q = a?b:(c?d:(e?f:g));
5. 运算符分类
运算符可以根据其操作数的个数进行分类。JavaScript中的大多数运算符(比如“*”乘法运算符)是一个二元运算符(binary operator),将两个表达式合并成一个稍复杂的表达式。换言之,它们的操作数均是两个。JavaScript同样支持一些一元运算符(unary operator),它们将一个表达式转换为另一个稍复杂的表达式。表达式-x中的“-”运算符就是一个一元运算符,是将操作数x求负值。最后,JavaScript支持一个三元运算符(ternary operator),条件判断运算符“?:”,它将三个表达式合并成一个表达式。
6. 省略对象创建表达式的括号
如果一个对象创建表达式不需要传入任何参数给构造函数的话,那么这对空圆括号是可以省略掉的:
new Object new Date
7. 函数作用域
JavaScript中没有块级作用域。JavaScript取而代之地使用了函数作用域(function scope):变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的。
8. 作用域链
每一段JavaScript代码(全局代码或函数)都有一个与之关联的作用域链(scope chain)。这个作用域链是一个对象列表或者链表,这组对象定义了这段代码“作用域中”的变量。当JavaScript需要查找变量x的值的时候(这个过程称做“变量解析”(variable resolution)),它会从链中的第一个对象开始查找,如果这个对象有一个名为x的属性,则会直接使用这个属性的值,如果第一个对象中不存在名为x的属性,JavaScript会继续查找链上的下一个对象。如果第二个对象依然没有名为x的属性,则会继续查找下一个对象,以此类推。如果作用域链上没有任何一个对象含有属性x,那么就认为这段代码的作用域链上不存在x,并最终抛出一个引用错误(ReferenceError)异常。
在JavaScript的最顶层代码中(也就是不包含在任何函数定义内的代码),作用域链由一个全局对象组成。在不包含嵌套的函数体内,作用域链上有两个对象,第一个是定义函数参数和局部变量的对象,第二个是全局对象。在一个嵌套的函数体内,作用域链上至少有三个对象。
作用域链的用途:保证对执行环境有权访问的所有变量和函数的 有序访问。
当代码在一个执行环境中执行时,就会创建变量对象的一个作用域链。
9. this
this并不是一个常量,它在程序的不同地方返回的值也不相同。this关键字经常在面向对象编程中出现。在一个方法体内,this返回调用这个方法的对象。
10. 补充分号
需要注意的是,JavaScript并不是在所有换行处都填补分号:只有在缺少了分号就无法正确解析代码的时候,JavaScript才会填补分号。换句话讲(类似下面代码中的两处异常),如果当前语句和随后的非空格字符不能当成一个整体来解析的话,JavaScript就在当前语句行结束处填补分号。看一下如下代码:
var a a = 3 console.log(a) //JavaScript将其解析为: var a; a = 3; console.log(a);
JavaScript给第一行换行处添加了分号,因为如果没有分号,JavaScript就无法解析代码var a a。第二个a可以单独当做一条语句“a;”,但JavaScript并没有给第二行结尾填补分号,因为它可以和第三行内容一起解析成“a=3;”。
11. 垃圾回收
JavaScript解释器有自己的内存管理机制,可以自动对内存进行垃圾回收(garbage collection)。这意味着程序可以按需创建对象,程序员则不必担心这些对象的销毁和内存回收。当不再有任何引用指向一个对象,解释器就会知道这个对象没用了,然后自动回收它所占用的内存资源。
12. NaN
JavaScript中的非数字值有一点特殊:它和任何值都不相等,包括自身。也就是说,没办法通过x==NaN来判断变量x是否是NaN。相反,应当使用x!=x来判断,当且仅当x为NaN的时候,表达式的结果才为true。
13. 字符串的比较
如果比较两个单独的字符串,当且仅当它们的长度相等且每个索引的字符都相等时,JavaScript才认为它们相等。
14. 使用字符串的方法不会改变原字符串
在JavaScript中字符串是固定不变的,类似replace()和toUpperCase()的方法都返回新字符串,原字符串本身并没有发生改变。
15. 包装对象
字符串既然不是对象,为什么它会有属性呢?只要引用了字符串s的属性,JavaScript就会将字符串值通过调用new String(s)的方式转换成对象,这个对象继承了字符串的方法,并被用来处理属性的引用。一旦属性引用结束,这个新创建的对象就会销毁。
存取字符串、数字或布尔值的属性时创建的临时对象称做包装对象,它只是偶尔用来区分字符串值和字符串对象、数字和数值对象以及布尔值和布尔对象。通常,包装对象只是被看做是一种实现细节,而不用特别关注。由于字符串、数字和布尔值的属性都是只读的,并且不能给它们定义新属性,因此你需要明白它们是有别于对象的。
16. 位运算符
& 按位与 只有两个为1 结果为1 其他为0
| 按位或 只要有一个为1 结果为1 两个0为0
^ 按位异或 两个相同时为0 不相同为1
~ 按位非 将操作数的所有位取反,相当于改变它的符号并减1
<< 左移 将操作数的所有二进制位向左移动,左移一位,相当于乘2,左移两位,相当于乘4
>> 右移 将操作数的所有二进制向右移动,右移一位,相当于除2,右移两位,相当于除4