JavaScript之表达式和运算符

表达式

  • 数组初始化表达式中,逗号之间的元素可以省略,空位会填充undefined
  • 在对象初始化表达式中,属性名称可以是字符串而不是标识符。

运算符概述

   类型列表示期望的操作数类型,以及运算符结果类型。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
  • 属性访问表达式和调用表达式的优先级要比所有运算符都高。

左值

  • ECMAScript规范允许内置函数返回一个左值,但是自定义函数不能返回左值,不过如果返回的是对象的话,可以访问其属性。

+ 运算法

  • + 运算法即可以作为加法运算,也可以作为字符串连接,但是优先考虑字符串连接。
  • 如果操作数中没有字符串,则都转化为数字。
  • 加法操作符的行为表现为
    • 如果其中一个操作时是对象,则尊照对象到原始值的转换规则转为原始值。
    • 转化为原始值后,如果其中一个操作数是字符串的话,则转化为字符串
    • 否则,两个操作数都转换为数字进行加法操作

位运算符

  • 位运算会将操作数转换为数字,并强制表示为32位整数,这会忽略原格式中的小数部分和任何超过32位的二进制。
  • 移位运算符要求右操作数在0~31之间,在将其操作数转化为无符号32位整数后,将舍弃第5位之后的二进制数。
  • 位运算会将NaN、Infinity和-Infinity转换为0。

相等和不等运算

严格相等运算符

  • “===”首先计算操作数的值,然后比较这两个值,比较过程中没有任何类型转换。
  • 如果两个值类型不相同,则它们不想等。
  • 如果两个值都是 null或者都是undefined,则它们相等,nullundefined不相等。
  • 如果其中一个值是NaN或者两个值都是NaN,则它们不相等。
  • 如果两个值为数字且数值相等,则它们相等,0===-0 = true
  • 如果两个值为字符串,且所含的对应位上的16位数完全相等,则它们相等。
  • 如果两个引用值指向同一对象、数组或函数,则它们是相等的。

相等运算符

  • 如果两个操作数类型一样,则执行严格相等一样的比较规则。
  • 如果两个操作数的类型不一样,则遵守如下规则:
    • null==undefined = true
    • 字符串和数字比较时,将字符串转换为数字,再做比较
    • 如果其中一个操作数为布尔类型,则将其转换为数字再做比较。
    • 如果是对象和数字或字符串对比,按照对象转原始值的转换规则转换为原始值。
    • 其它不同类型之间的比较均不相等。

关系运算符

  • 只有数字和字符串才能真正的执行比较操作。
  • 如果操作数中不都包含字符串时,则都转化为数字进行数值比较。
  • 0等于-0,Infinity比任何数都大(除了本身),-Infinity比任何数都小(除了本身)。
  • 其中一个操作数为NaN,比较操作符总是返回false

逻辑表达式

  • 在逻辑与运算中,JavaScript先计算左操作数,如果为假植,则直接返回假植,如果为真值则返回右操作数的计算结果。
  • 在逻辑或中,当左操作数为真值时,返回该值。

带操作的赋值运算

  • a op= b等价于 a=a op bop代表一个运算符。第一个表达式中a只计算了一次,第二个表达式中a计算了两次。
  • a是带有副作用的表达式时,两者不等价。

eval()

  • eval()是一个函数,但被当作运算符对待。
  • eval()只有一个参数,如果传入的参数不是字符串,只是简单的返回这个参数。
  • eval()将传入的字符串进行编译,编译失败抛出语法错误,编译成功则执行这段代码,并返回最后一个表达式或者语句的值,如果该语句没有值,则返回undefined
  • eval()的字符串执行时的上下文环境和调用函数的上下文环境是一样的。
  • eval()的字符串必须在语法上讲的通。
  • ECMAScript 3规范规定不允许对eval()赋予别名,实际上大多数实现很少这么做。
  • 当通过别名调用时,eval()会将其字符串当成顶层的全局代码执行,执行的代码可能会修改或创建新的全局变量和全局函数,但不会使用主调函数的局部变量。
  • ECMAScript 5规定,当直接使用eval()时,在调用它的上下文作用域内执行,当使用别名调用时则使用全局对象作为上下文作用域,并且无法访问定义局部变量和函数。

严格模式下的eval

当在严格模式下,或者eval()执行的代码段以"use strict"开头时,无法定义新的局部变量和函数,只能查询或更改局部变量。

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”。

delete 运算符

  • delete删除属性成功将返回true
  • delete无法删除内置核心、客户端属性、通过var声明的变量、function定义的函数、函数参数。
  • 在严格模式下,delete的操作数是非法时,将抛出语法错误异常,如果操作数是不可配置的属性,将抛出类型错误异常。

void 运算符

  • void运算符出现在操作数之间,操作数会照常计算,但忽略计算结果并返回undefined