3.1语法
ECMAScript中的一切(变量、函数名和操作符)都区分大小写。
标识符,就是指变量、函数、属性的名字,或者函数的参数。
按照惯例、ECMAScript标识符采用驼峰大小写格式。
/*
* 注释
*
*/
注释的第二行和第三行的星号可省略,这不是必需的,目的是为了提高可读性。
语句结尾的分号不是必需的,但我们建议任何时候都不要省略它。因为它能帮助开发人员避免不完整错误、保证代码压缩正确、在某些情况下增加代码性能。
if语句的最佳实践是始终都在控制语句中使用代码块,即使只有一条语句。
3.2关键字和保留字
关键字:
debugger*——调用任何可用的调试功能,设置断点
in——A in B 判断A是否是B的属性/索引
instanceof——A instanceof B 判断A是否是B的实例
with——扩展语句作用域链(不推荐使用)
3.3变量
可以在修改变量值的同时修改值的类型如,有效,但不推荐。
var m = 'hi';
m=100;
3.4数据类型
对未声明但变量执行typeof操作符会返回undefined值
null值表示空对象指针。typeof null;//"object"
如果定义的变量将来准备用来保存对象,最好初始化为null而不是其他值。这样一来,只要一检查null值就可以知道相应变量是否保存了一份对象但引用。
实际上undefined值派生自null值,因此alert(undefined==null);//true
Number类型中,整数可以用八进制字面量表示,前导为0:
var octalNum1 = 070; //八进制56
var octalNum2 = 079; //无效但八进制数值,解析为79
var octalNum3 = 08; //无效但八进制数值,解析为8
整数也可以用十六进制自面量表示,前导为0x:
var hexNum1 = 0xA; //十六进制的10
var hexNum2 = 0x1f; //十六进制的31
对于浮点数值,允许小数点前没有整数(如var a = .1;)但不推荐这种写法。
保存浮点数值占用的内存是整数的两倍,因此ECMAScript会不失时机地将浮点数解析为整数(如当小数点后都为0的情况)。
e表示法(科学技术法):e前面的数值乘以10的指数次幂。(e/E均可)
浮点数运算的精度远不如整数。
由于内存限制,ECMAScript能保存的最大数值Number.MAN_VALUE;最小数值Nubmer.MIN_VALUE;如果超出这个范围,则被转换为特殊的Infinity值(无穷大),如果是负数则-Infinity。如果想确定一个数值是不是有穷的,使用isFinite()函数。
访问Number.NEGATIVE_INFINITY和Number.POSITIVE_INFINITY可以得到负和正的Infinity值。
NaN即非数值,任何涉及NaN的操作都返回NaN,NaN 和任何值都不想等,包括NaN本身。
isNaN()函数确定参数是否是“非数值”。尽管有点不可思议:它也适用于对象,它会调用对象的valueOf()方法判断是否为数值,如果不能转化为数值,则基于返回值再调用toString()方法再次测试返回值。
对于Number()函数,如果传入字符串时,如果字符串为空,则转化为0,如果传入的是对象时,调用valueOf()方法返回值,如果结果是NaN,则调用toString()方法,再次常规的方法转化字符串值。
var num1 = Number('Hello'); //NaN
var num2 = Number(''); //0
var num3 = Number('00011'); //11
var num4 = Number(true); //1
在处理整数时更常用的时parseInt()函数。它会从第一个字符开始解析,一直解析到所有连续的数字字符就停止。
var num = parseInt('1234blue'); //1234
var num2 = parseInt(22.5); //22
parseInt()可以传入第二个参数,代表以多少进制进行转换。
对于parseFloat()如果字符串是一个可以解析为整数的值,则parseFLoat()返回一个整数。
字符字面量,又叫做转义序列:
字面量 | 含义 |
---|---|
\n | 换行 |
\t | 制表 |
\b | 退格 |
\r | 回车 |
\f | 进纸 |
\\ | 斜杠 |
\' | 单引号(')在单引号表示的字符串中使用。例如'He said, \' hey \' ' |
\" | 双引号(")在单引号表示的字符串中使用。例如"He said, \" hey \" " |
\xnn | 以十六进制代码nn表示的一个字符(其中n为0~F)。 |
\unnnn | 以十六进制nnnn表示的一个Unicode字符(其中n为0~F)。例如\u03a3表示希腊字符Σ |
这些字面量被作为一个字符解析,如\u03a3就是一个字符。
ECMAScript字符串是不可变的, 要改变变量的字符串值,就要销毁原来的字符串,再用另一个包含新值的字符串填充该变量。
null和undefined没有toString()方法。
num.toString(8);表示将num转化为八进制,十六进制、二进制同理。
可以用String()将任何类型的值转化为字符串。
Object实例的属性constructor保存着用于创建当前对象函数。对于var f = new Obejct()而言,就是Object();hasOwnProperty(propertyName);检查给定属性是否在当前对象实例中。
从技术角度讲,ECMA-262中对象的行为不一定适用于JavaScript中的其他对象。浏览器环境中的对象,如DOM和BOM属于宿主对象,他们是由宿主实现提供和定义的。ECMA-262不负责定义宿主对象,因此宿主对象也可能不继承Object。
3.5操作符
操作符 包括算术操作符(+、-)、关系操作符(~、^)、关系操作符(> 、<=)和相等操作符。
计算二进制补码
- 求数值绝对值的二进制码(例如,要求-18的二进制补码,先求18的二进制补码)
- 求二进制反码。即将0替换成1,1替换成0。
- 得到二进制反码加1。
要根据这三个步骤求得-18的二进制码,首先要求得18的二进制码,即:
0000 0000 0000 0000 0000 0000 0001 0010
然后,求其二进制反码,即0和1互换:
1111 1111 1111 1111 1111 1111 1110 1101
最后,二进制反码加1:
1111 1111 1111 1111 1111 1111 1110 1101
1
1111 1111 1111 1111 1111 1111 1110 1110
这样就求得了-18的二进制表示,即11111111111111111111111111101110
ECMAScript会尽力隐藏这些信息。换句话说,在以二进制字符串形式输出一个负数时,我们看到的只是这个负数绝对值的二进制码前面加了个负号。例如:
var num = -18; alert(num.toString(2)); //'-10010'
按位非(NOT)执行按位非的结果就是返回数值的反码,用波浪线(~)表示。按位非的本质:操作数的负值减1,虽然十进制的减法也能得到这种结果,但是由于按位非是在数值表示的最底层执行操作,因此操作更快。
按位与(AND)相当于数学上的“交”,用和号字符(&)表示。
按位或(OR)相当于数学上的“并”,用竖线符号(|)表示。
按位异或(XOR)对于底层位运算,相同为0,不同为1,用插入负号(^)表示。
左移,用两个小于号(<<)表示。左移n位后,原数值右侧多出n个空位,用0填充。
有符号的右移,用两个大于号(>>)表示。右移后,左侧所有的空位用负号位的值填充。
无符号的右移,用三个大于号(>>>)表示。对于正数来说,结果与有符号右移相同;对于负数来说,右移以0填充空位,并且无符号右移操作符会把负数的二进制码当作正数的二进制码,进而导致右移结果非常大。
逻辑非,用感叹号(!)表示。
逻辑与,用两个和号(&&)表示。逻辑与操作属于短路操作,如果第一个操作数能够决定结果,就不会再对第二个操作数求值。
逻辑或,用两个竖线(||)表示。也属于短路操作,同上。
我们可以利用逻辑或的短路行为来避免为变量赋值null或undefined值:
var myObject = preferredObject || backupObject;
在这个例子中,变量myObject将被赋予等号后面两个值中的一个。变量preferredObject中包含优先赋给变量myObject的值,变量backupObject负责在preferredObject中不包含有效值的情况下提供后备值。如果preferredObject的值不是null,那么它的值将被赋予给myObject;如果是null,则将backupObject的值赋给myObject。
对于求模,如果被除数是零,则结果为零。例如 0%5=0;
相等和不相等——先转换再比较。由两个等于号(==)和感叹号加等于号(!=)表示。这两个操作符都会先强制转型然后仔比较相等性。(null==undefined返回true)
全等和不全等——不转换,直接比较。由三个等于号(===)和感叹号加两个等于号(!==)表示。
逗号操作符在用于赋值时,总会返回表达式中的最后一项:
var num = {1,2,3,4,5};//num的值是5
3.6语句
条件语句中,业界普遍推崇的最佳实践始终使用代码块,即使要执行的只有一行代码。
do-while语句常用于代码至少要被执行一次。
while语句代码有可能永远不会执行。
for-in语句是一种精准迭代语句,可以用来枚举对象的属性。ECMA对象的属性没有顺序,通过for-in语句输出的属性名顺序是不可预测的。
label语句可以在代码中添加标签,在将来由break和continue语句引用。
with语句的作用是将代码的作用域设置到一个特定的对象中。不推荐使用with语句。
在switch-case语句中,如果确实需要混合几种情况,不要忘记加注释,说明是你有意忽略break关键字:
switch(i){
case 25:
/*合并两种情形*/
case 26:
alert('hi');
default:
alert('other');
}
switch在比较值时使用的是全等操作符,因此不会发生类型转换(例如,字符串“10”不等于10)。
3.7函数
推荐要么让函数始终都有一个返回值,要么永远不要返回。
严格模式对函数有一些限制:
- 不能把函数命名成eval或arguments;
- 不能把参数命名为eval或arguments;
- 不能出现两个命名参数相同的情况。
在ECMAScript中的参数是用数组表示的,在函数体内部,可以通过arguments对象来访问这个数组。
没有传递值的命名参数将被自动赋予undefined
ECMAScript不能像传统意义上实现重载,因为其他语言(如Java)在接受参数时还由类型标识,但是如果相同函数被定义两次,就会发生覆盖。