本文是《JavaScript 权威指南》的整理和总结
1 表达式
- 数组初始化表达式中,逗号之间的元素可以省略,空位会填充
undefined
。 - 在对象初始化表达式中,属性名称可以是字符串而不是标识符。
2 运算符概述
类型列表示期望的操作数类型,以及运算符结果类型。lval 表示左值。
运算符 | 操作 | A | N | 类型 |
---|---|---|---|---|
++ | 前 / 后增量 | R | 1 | lval -> num |
– | 前 / 后减量 | R | 1 | lval -> num |
- | 求反 | R | 1 | num->num |
+ | 转换为数字 | R | 1 | num->num |
~ | 按位求反 | R | 1 | int->int |
! | 逻辑非 | R | 1 | bool->bool |
delete | 删除属性 | R | 1 | lval->bool |
typeof | 检测操作数类型 | R | 1 | any->str |
void | 返回 undefined 值 | R | 1 | any->undef |
| 乘、除、求余 | L | 2 | num,num->num |
+、- | 加、减 | L | 2 | num,num->num |
+ | 字符串连接 | L | 2 | str,str->str |
<< | 左移位 | L | 2 | int,int->int |
> | 有符号右移 | L | 2 | int,int->int |
> | 无符号右移 | L | 2 | int,int->int |
<、 <=、>、>= | 比较数字顺序 | L | 2 | num,num->bool |
<、 <=、>、>= | 比较在字母表中的顺序 | L | 2 | str,str->bool |
instanceof | 测试对象类 | L | 2 | obj,func->bool |
in | 测试属性是否存在 | L | 2 | str,obj->bool |
== | 判断相等 | L | 2 | any,any->bool |
!= | 判断不等 | L | 2 | any,any->bool |
=== | 判断恒等 | L | 2 | any,any->bool |
!== | 判断非恒等 | L | 2 | any,any-bool |
& | 按位与 | L | 2 | int,int->int |
^ | 按位异或 | L | 2 | int,int->int |
| | 按位或 | L | 2 | int,int->int |
&& | 逻辑与 | L | 2 | any,any->any |
| | | 逻辑或 | L | 2 | any,any->any |
? : | 条件运算符 | R | 3 | bool,any,any->any |
= | 变量赋值或对象属性赋值 | R | 2 | lval,any->any |
*= 、/=、%=、+=、-=、&= ^=、|=、<<=、>>=、>>>= | 运算且赋值 | R | 2 | lval,any->any |
, | 忽略第一个操作数,返回第二个操作数 | L | 2 | any,any->any |
* 属性访问表达式和调用表达式的优先级要比所有运算符都高。
2.1 左值
- ECMAScript 规范允许内置函数返回一个左值,但是自定义函数不能返回左值,不过如果返回的是对象的话,可以访问其属性。
2.2 + 运算法
-
- 运算法即可以作为加法运算,也可以作为字符串连接,但是优先考虑字符串连接。
- 如果操作数中没有字符串,则都转化为数字。
- 加法操作符的行为表现为:
- 如果其中一个操作时是对象,则尊照对象到原始值的转换规则转为原始值。
- 转化为原始值后,如果其中一个操作数是字符串的话,则转化为字符串
- 否则,两个操作数都转换为数字进行加法操作
2.3 位运算符
- 位运算会将操作数转换为数字,并强制表示为 32 位整数,这会忽略原格式中的小数部分和任何超过 32 位的二进制。
- 移位运算符要求右操作数在 0~31 之间,在将其操作数转化为无符号 32 位整数后,将舍弃第 5 位之后的二进制数。
- 位运算会将 NaN、Infinity 和 - Infinity 转换为 0。
2.4 相等和不等运算
2.4.1 严格相等运算符
- “===” 首先计算操作数的值,然后比较这两个值,比较过程中没有任何类型转换。
- 如果两个值类型不相同,则它们不想等。
- 如果两个值都是
null
或者都是undefined
,则它们相等,null
和undefined
不相等。 - 如果其中一个值是
NaN
或者两个值都是NaN
,则它们不相等。 - 如果两个值为数字且数值相等,则它们相等,
0===-0 = true
。 - 如果两个值为字符串,且所含的对应位上的 16 位数完全相等,则它们相等。
- 如果两个引用值指向同一对象、数组或函数,则它们是相等的。
2.4.2 相等运算符
- 如果两个操作数类型一样,则执行严格相等一样的比较规则。
- 如果两个操作数的类型不一样,则遵守如下规则:
null==undefined = true
- 字符串和数字比较时,将字符串转换为数字,再做比较
- 如果其中一个操作数为布尔类型,则将其转换为数字再做比较。
- 如果是对象和数字或字符串对比,按照对象转原始值的转换规则转换为原始值。
- 其它不同类型之间的比较均不相等。
2.5 关系运算符
- 只有数字和字符串才能真正的执行比较操作。
- 如果操作数中不都包含字符串时,则都转化为数字进行数值比较。
- 0 等于 - 0,
Infinity
比任何数都大 (除了本身),-Infinity
比任何数都小 (除了本身)。 - 其中一个操作数为
NaN
,比较操作符总是返回false
。
2.6 逻辑表达式
- 在逻辑与运算中,JavaScript 先计算左操作数,如果为假植,则直接返回假植,如果为真值则返回右操作数的计算结果。
- 在逻辑或中,当左操作数为真值时,返回该值。
2.7 带操作的赋值运算
a op= b
等价于a=a op b
。op
代表一个运算符。第一个表达式中a
只计算了一次,第二个表达式中a
计算了两次。- 当
a
是带有副作用的表达式时,两者不等价。
2.8 eval()
- eval() 是一个函数,但被当作运算符对待。
- eval() 只有一个参数,如果传入的参数不是字符串,只是简单的返回这个参数。
- eval() 将传入的字符串进行编译,编译失败抛出语法错误,编译成功则执行这段代码,并返回最后一个表达式或者语句的值,如果该语句没有值,则返回
undefined
。 - eval() 的字符串执行时的上下文环境和调用函数的上下文环境是一样的。
- eval() 的字符串必须在语法上讲的通。
- ECMAScript 3 规范规定不允许对 eval() 赋予别名,实际上大多数实现很少这么做。
- 当通过别名调用时,eval() 会将其字符串当成顶层的全局代码执行,执行的代码可能会修改或创建新的全局变量和全局函数,但不会使用主调函数的局部变量。
- ECMAScript 5 规定,当直接使用 eval() 时,在调用它的上下文作用域内执行,当使用别名调用时则使用全局对象作为上下文作用域,并且无法访问定义局部变量和函数。
2.8.1 严格模式下的 eval
- 当在严格模式下,或者 eval() 执行的代码段以
"use strict"
开头时,无法定义新的局部变量和函数,只能查询或更改局部变量。
2.9 typeof 运算符
x | typeof x |
---|---|
undefined | “undefined” |
null | “object” |
true 或 false | “boolean” |
任意数字或 NaN、Infinity | “number” |
任意字符串 | “string” |
任意函数 | “function” |
任意内置对象 非函数 | “object” |
任意宿主对象 | 由编译器各自实现的字符串 ,但不是 “undefined”、”boolean”、”number”、”string” |
* ECMAScript 3 规范规定所有内置可执行对象,typeof 一律返回”function”。
* ECMASCript 5 规范规定所有可执行对象,包括内置对象和数组对象一律返回”function”。
2.10 delete 运算符
- delete 删除属性成功将返回
true
- delete 无法删除内置核心、客户端属性、通过
var
声明的变量、function
定义的函数、函数参数。 - 在严格模式下,delete 的操作数是非法时,将抛出语法错误异常,如果操作数是不可配置的属性,将抛出类型错误异常。
2.11 void 运算符
- void 运算符出现在操作数之间,操作数会照常计算,但忽略计算结果并返回
undefined