JavaScript高级程序设计4 第三章 语言基础
变量
- 使用var操作符定义的变量会成为包含它的函数的局部变量。比如,使用var在一个函数内部定义一个变量,就意味着该变量将在函数退出时被销毁。
- 在严格模式下,不能定义名为eval和arguments的变量,否则会导致语法错误。
- let声明的范围是块作用域,而var声明的是函数作用域。
- 块作用域是函数作用域的子集,因此适用于var的作用域限制同样也适用于let
- 在解析代码是,JavaScript引擎也会注意出现在块后面的let声明,只不过在此之前不能以任何方式来引用未声明的变量。在let声明之前的执行瞬间被称为“暂时性死区”
- 与var关键字不同,使用let在全局作用域中声明的变量不会成为window对象的属性(var声明的变量则会)
- 用const声明变量时必须同时初始化变量,且尝试修改const声明的变量会运行时报错
- const声明的限制只适用于它指向的变量的引用。换句话说,如果const变量引用的是一个对象,那么修改这个对象内部的属性并不违反const的限制。
数据类型
- ECMAScript有6种简单数据类型(也称为原始类型):Undefined、Null、Boolean、Number、String和Symbol
- typeof是一个操作符而不是函数
- 使用var或let声明了变量但没有初始化时,就相当于给变量赋予了undefined值
- 对未声明的变量,只能执行一个有用的操作,就是对他调用typeof,返回undefined
- null值表示一个空对象指针
- undefined值是由null值派生而来的,因此他们表面上相等。
- 只要变量要保存对象,而当时有没有那个对象可保存,就要用null来填充该变量。这样就可以保持null是一个空对象指针的语义,并进一步将其与undefined区分开来。
- 布尔值字面量true和false是区分大小写的。
- 可以转为false的值:false,'',0、NaN,null,undefined
- 浮点值使用的内存空间是存储整数数值的两倍
- 数值超过JavaScript可以表示的范围,会转为Infinity
- 要确定一个值是不是有限大(介于最大值最小值之间),可以使用isFinite()函数。
- 任何涉及NaN的操作始终返回NaN
- NaN不等于包括NaN在内的任何值
- 如果第一个字符不是数值字符、加号或减号,parseInt()立即返回NaN
- parseInt()也接受第二个参数,用于指定底数(进制数)
- 不传参数相当于让parseInt()自己决定如何解析,所以为避免解析出错,建议始终传递给它第二个参数。
- parseFloat()只解析十进制的值,因此不能指定底数。
- 字符串可以使用双引号,单引号,或反引号标示
- 转义序列表示一个字符。
- ECMScript中的字符串是不可变的,意思是一旦创建,他们的值就不能变了。要修改某个变量的字符串值,必须先销毁原始的字符串,然后将包含新值得另一个字符串保存到该变量。
- toString()方法唯一的用途就是返回当前值得字符串等价物
- null和undeifned值没有toString()方法。
- 模板字面量在定义时立即求值并转换为字符串实例,任何插入的变量也会从他们最接近的作用域中取值,字符串插值通过在${}中使用一个JavaScript表达式实现,插入的值会使用toString()强制转型为字符串,而且任何JavaScript表达式都可以用于插值
- 在插值表达式中可以调用函数和方法。
Symbol类型
- Symbol符号是原始值,且符号实例时唯一的,不可变的。符号的用途是确保对象属性使用唯一标识符,不会发生属性冲突的危险
- 符号就是用来创建唯一记号,进而用作非字符串形式的对象属性。
- 符号没有字面量语法,只要创建Symbol()实例并将其用作对象新属性,就可以保证他不会覆盖已有的对象属性,无论是符号属性还是字符属性
- Symbol()函数不能与new关键字一起作为构造函数使用。这样做是为了避免创建符号包装对象。
- Symbol.for()对每个字符串键都执行幂等操作。第一次使用某个字符串调用时,他会检查全局运行时注册表,发现不存在对应的符号,于是生成一个新符号实例并添加到注册表中,后续使用相同字符串调用同样会检查注册表,发现存在与该字符串对应的符号,然后就会返回该符号实例
- 使用Symbol.keyFor()来查询全局注册表
- Object.getOwnPropertyNames()返回对象实例的常规属性数组,Object.getOwnProperty-Symbols()返回对象实例的符号属性数组。这两个方法的返回值互斥。Object.getOwnProperty-Descriptors()会返回同时包含常规和符号属性描述符的对象。Reflect.ownKeys()会返回两种类型的键。
Object类型
- 对象其实就是一组数据与功能的集合。
- constructor()用于创建当前对象的函数。
- hasOwnProperty(propertyName)用于判断当前对象实例(不是原型)上是否存在给定的属性
- isPrototyperOf(object)用于判断当前对象是否为另一个对象的原型。
- toLocaleString()返回对象的字符串表示
- toString()返回对象的字符串表示
- valueOf()返回对象的字符串、数值或布尔值表示。
操作符
一元操作符
- 只操作一个值的操作符叫做一元操作符。
- 使用前缀递增还是前缀递减操作符,变量的值都会在语句被求值之前改变
- 后缀递增、递减在语句被求值后才发生。
- 递增、递减操作符遵循如下规则:
- 对于字符串,如果是有效的数值形式,则转换为数值再应用改变。变量类型从字符串变为数值。
- 对于字符串,如果不是数值形式,则将变量值设置为NaN,类型由字符串变为数值
- 对于布尔值,如果是false,则转换为0再改变,类型从布尔变为数值。
- 对于布尔值,如果是true,则转换为1再改变,类型从布尔变为数值。
- 如果是对象则调用valueOf(),取得可操作的值,再按照以上规则改变。
位操作符
- 有符号整数使用32位的前31位表示整数值。第32位表示数值的符号,如0表示正,1表示负
- 正值以真正的二进制格式存储,即31位中每一位都代表2的幂
- 负值以一种成为二补数(或补码)的二进制编码存储
- 确定绝对值的二进制表示
- 找到数值的一补数或反码
- 给结果加1
- 特殊值NaN和Infinity在位操作中都会被当成0处理
- 如果将位操作符应用到非数值,首先会使用Number()函数将该值转为数值,然后再进行位操作
- 按位非操作符用~表示,他的作用是返回数值的一补数
- 按位与(&)操作在两个位都是1时返回1,在任何一位是0时返回0
- 按位或(|)操作在至少一位是1时返回1,两位都是0时返回0
- 按位异或(^)与按位或的区别是,他只在一位上是1是1的时候返回1(两位都是1或0,返回0)
- 左移操作符用两个小于号(<<)表示,会按照指定的位数将数值的所有位向左移动。
- 左移会保留他所操作数值的符号。
- 有符号右移由两个大于号(>>)表示,会将数值的所有32位都向右移,同时保留符号
- 无符号右移(>>>)会将数值的所有32位都向右移。对于正数,无符号右移与有符号右移结果相同。
布尔操作符
逻辑非操作符遵循如下规则:
- 操作数是对象,返回false
- 操作数是空字符串,返回 true
- 操作数是非空字符串,返回false
- 操作数是数值0返回true
- 操作数是非0数值包括(Infinity),返回false
- 操作数为null 返回true
- 操作数是undefined返回true
- 操作数是NaN返回true
逻辑非操作符也可以用于把任意值转为布尔值。同时使用两个叹号(!!),相当于调用了转型函数Boolean()
逻辑与操作规则:
- 如果第一个操作数为对象,则返回第二个操作数
- 如果第二个操作数为对象,则只有第一个操作数为true才会返回该对象。
- 如果两个操作数都是对象,则返回第二个操作数。
- 如果有一个操作数为null,则返回null
- 如果有一个操作数为NaN,返回NaN
- 如果有一个操作数为undefined则返回undefined
逻辑或操作规则:
- 如果第一个操作数是对象,则返回第一个操作数
- 如果第一个操作数求值为false,则返回第二个操作数
- 如果两个操作数都是对象,则返回第一个操作数
- 如果两个操作数都为null则返回null
- 如果两个操作数都是NaN,则返回NaN
- 如果两个操作数都是undefined,则返回undefined
逻辑或操作符也具有短路的特性,第一个操作数求值为true,第二个操作数就不会被求值了。
乘性操作符
乘性操作符有不是数值的操作数,则该操作数会在后台被使用Number()转型函数转为数值。
乘法操作符的一些特殊行为:
- 如果不能表示乘积,则返回Infinity或-Infinity
- 如果有任一操作数是NaN,则返回NaN
- 如果是Infinity乘以0,返回NaN
- 如果Infinity乘以非0的有限数值,则根据第二个操作数符号返回Infinity或-Infinity
- 如果Infinity乘以Infinity则返回Infinity
- 如果有不是数值的操作数,则先用Number()转为数值再操作。
除法操作符针对特殊值的一些特殊行为:
- 如果不能表示商则返回Infinity或-Infinity
- 如果有任一操作数是NaN则返回NaN
- 如果是Infinity除以Infinity则返回NaN
- 如果0除以0 则返回NaN
- 如果是非0的有限值除以0,则根据第一个操作数的符号返回Infinity或-Infinity
- 如果Infinity除以任何数值,则根据第二个操作数的符号,返回Infinity或-Infinity
- 如果有不是数值的操作数,则先用Number()转为数值再操作。
取模操作符对特殊值的一些特殊行为:
- 如果操作数是数值,则执行常规除法运算,返回余数
- 如果被除数是无限值,除数是有限值,则返回 NaN
- 如果被除数是有限值,除数是 0,则返回 NaN。
- 如果是 Infinity 除以 Infinity,则返回 NaN。
- 如果被除数是有限值,除数是无限值,则返回被除数。
- 如果被除数是 0,除数不是 0,则返回 0。
- 如果有不是数值的操作数,则先在后台用 Number()函数将其转换为数值,然后再应用上述规则
指数操作符
使用Math.pow(底数,指数)
相等操作符
转换操作数类型时,相等和不相等操作符遵循如下规则:
- 如果任一操作数是布尔值,则将其转换为数值再比较是否相等。false转换为0,true转换为1
- 如果一个操作数是字符串,则另一个操作数是数值,则尝试将字符串转换为数值再比较
- 如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法取得其原始值,再比较
- null和undefined的相等
- null和undefined不能转换为其他类型再进行比较
- 如果有任一操作数为NaN,则相等操作符返回false,不相等操作符返回true
- 如果两个操作数都是对象,则比较他们是不是同一个对象,如果两个操作数都指向同一对象,则相等。