表达式和运算符
JavaScript求对象初始化表达式的值的时候,对象表达式也都会各自计算一次,并且它们不必包含常数值
属性访问表达式
不管使用哪种形式的属性访问表达式,在“.”和“[”之前的表达式总是会首先计算,如果计算结果是null或undefined,表达式会抛出一个类型异常错误,因为这两个值都不能包含任何属性。如果运算结果不是对象或数组,JavaScript会将其转为对象。如果命名的属性不存在,则返回undefined
如果属性名称是一个保留字或者包括空格和标点符号,或是一个数字(对于数字),则必须使用方括号的写法。
调用表达式
当对调用表达式进行求值当时候,首先计算函数表达式,然后计算参数表达式,得到一组参数值。如果函数表达式的值不是一个可调用的对象,则抛出一个类型异常错误(所有的函数都是可调用的,就算宿主对象不是函数依旧可能被调用)然后,实参的值被依次赋值给形参,这些形参上定义函数时指定的,接下来开始执行函数题。如果函数使用return语句给回一个返回值,那么该返回值就是整个调用表达式的值。否则,调用表达式的值就是undefined。
对象创建表达式
如果一个对象创建表达式不需要传入任何参数给构造函数,则后面的圆括号可以省略
new Date
new Object
运算符
有些运算符对于操作数类型有着不同程度上的依赖,比如+
函数调用表达式和对象创建表达式是有副作用的
属性访问表达式和调用表达式的优先级要高过所有运算符
typeof my.functions[x](y)
尽管typeof时优先级最高的运算符之一,但typeofyes在两次属性访问和函数调用之后执行的。
赋值运算符的优先级非常低,通常总是最后执行
一元运算符、赋值和三元条件运算符都具有从右向左的结合性
运算符的优先级和结核性规定它们在复杂的表达式中的运算顺序,但没有规定自表达式的计算过程的运算顺序。JavaScript总是严格按照从左往右的顺序来计算表达式。给表达式添加圆括号会改变运算符间的关系,但是从左向的顺序事不会改变的。
只有在任何一个表达式具有副作用而影响到其它表达式的时候,其求值顺序才会和看上去有所不同。如果表达式x中的一个变了自增1,这个变量在表达式z中使用,那么实习生时现计算出了x的值再计算z的值。
var a=1;
var b=(a++)+a;
console.log(b) //3
算数表达式
%操作符的结果与第一个操作数保持一致。
+运算符中一个操作符时字符串或者转化为字符串的对象,那么另外一个操作数会被转化为字符串。如果两个都不是字符串,则进行算术加法运算。
从技术上讲,加法操作符行为如下:
- 一个是对象,则按照对象到原始值的转化规则转化为原始值:日期通过toString,其它通过valueOf,若无valueOf,则用toString
- 在进行了对象到原始值的转化后,如果一个操作符时字符串的话,则另一个也会转换为字符串,然后进行字符串链接。
- 否则,将两个操作数都转化为数字(或NaN),然后进行加法操作
一元运算符具有很高的优先级,而且都是右结合。+,-,++,--必要时会将操作数转化为数字。
如果x是字符串“1”,则++x的结果是2,而x+1是字符串“11”
由于JavaScript会自动进行分号不全,因此不能在后增量运算符和操作数之间插入换行符。如果插入了换行符,JavaScript将会吧操作数当成单独的语句,并在之前补上一个分号。
关系表达式
!=和!==是对==和===对求反
在严格运算下:
- 类型不同则不同
- 0===-0
- 两个字符串可能显示出对字符完全一样,但具有不同编码的16位值,javaScript不对Unicode进行标准化转转换
不严格模式下:
- 一个为null一个为undefined,相等
- 一个是数字,另一个是字符串,则转化为数字比较
- 一个是boolean值,则转换为数字(0,1),比较
- 一个是对象,另一个是数字或字符串,则对象转为原始值(Date先用toString)
比较运算符
- 如果有对象,则转化为原始值
- 若都为字符串,则按Unicode字典序排列
- 两个都转化为原始值后,若一个不是字符串,则转化为数字排序(涉及NaN就是false)
对于数字和字符串操作符而言,家好运算符和比较运算符的行为都有所不同,前者偏爱字符串,如果他的一个操作符时是字符串,则进行字符串链接操作。而比较运算符则偏爱数字,只有两个都是字符串的时候,才会进行字符串比较
"11"<"3" //true
11<"3" //false
instanceof运算符是基于原型链的
逻辑表达式
关系运算符的优先级要高过&&和||
在JavaScript中任何希望使用布尔值的地方,表达式和语句都会将其看作是布尔值,因此&&和||不一定总返回布尔值
&&和||会逻辑短路
赋值表达式
赋值操作符的结合性是从左向右,也就是说,如果一个表达式中出现了多个赋值运算符,运算顺序是从左向右的。
其它运算符
typeof运算符对函数会是“function”,对于内置对象则是“object”,对于宿主对象则是编译器生成的字符串
typeof对于任意可执行对象返回都是function
删除属性或者数组元素不仅仅是设置一个undefined的值。当删除一个属性时,这个属性将不再存在。读取一个一个不存在的属性返回undefined,而可通过in检测是否存在
void出现在操作数之前,操作数会照常计算,当忽略计算结果返回undefined。由于void会忽略操作数的值,因此在操作上具有副作用的时候使用void让程序更具语义化