0. 检测类型操作符
0.1 typeof
多用于基本类型检测,返回值有 string、number、boolean、undefined、object、function
检测
null会返回object检测函数时会返回
function
0.2 instanceof
用于检测对象类型
result = variable instanceof constructor;
所有引用类型的值都是
Object的实例,在检测引用类型值和Object构造函数时,instanceof操作符始终返回true使用
instanceof操作符检测基本类型的值时,始终返回false
1. 算术操作符
1.1 递增、递减
分为前置和后置
前置放在变量之前,表示先对变量加减
1后再进行变量的其他操作后置放在变量之后,表示一条语句结束后再对变量加减
1
对任何值都适用,包括字符串、布尔值、浮点数值和对象
包含有效数字字符的字符串时,先将其转换为数值,在执行加减
1操作,字符串变量变成数值变量不包含有效数字字符时,将变量的值设置为
NaN,字符串变量变成数值变量布尔值,
false变换成0,true变换成1,再进行加减1操作,布尔值变成数值变量浮点数值,直接进行加减
1操作对象,先调用对象的
valueOf()方法以取得一个可供操作的值,应用前面的规则,如果结果为NaN,再调用对象的toString()方法后再应用前面的规则。对象变量变成数值变量
注意:n++ 和 n = n + 1 一样吗? 当 n 是数字或其它类型的时候,是一样的 而当 n 是字符串时,一个依然是数学运算,另一个却是字符串拼接
var n = '10'n = n + 1; //=> n: '101'n++ //=> n: 11
1.2 一元加减
在对非数值应用一元加或减操作符时,会像 Number() 转型函数一样执行转换
var s = "01";s = +s; //s=1;{} + 'aa' //=> NaN,原因在于 {} 会被解析为代码块,后面就只是 + 'aa',就是一元加({}) + 'aa' //=> '[object Object]aa',这时就是字符串拼接
一元减主要用于表示负数
2. 位操作符
位操作符应用于最基本的层次上,按内存中表示数值的位来操作数值,同样效果中,速度更快
所有数值以 IEEE-754 64 位格式存储
默认情况下,所有的整数都是有符号整数
当数值应用位操作符时
64位数值被转换成32位数值执行位操作
将
32位数值转换为64位数值副效应:对特殊的
NaN和Infinity值应用位操作时,会被当0处理
对非数值应用位操作
- 自动使用
Number()函数转换为数值,然后应用位操作
- 自动使用
注意:在内存中,负数是以二进制补码的格式存储的,但是在将负数以二进制字符串形式输出时,我们看到的是负数的绝对值的二进制码前面加一个负号,而不是以补码形式展现。
2.1 按位非 ~
返回数值的反码,本质是操作数是负值减 1
2.2 按位与 &
两个数值的每一位对齐,对应位都是 1 时才返回 1,任何一位是 0,结果都是 0
2.3 按位或 |
两个数值的每一位对齐,对应位有一个是 1 就返回 1,都是 0 时返回 0
2.4 按位异或 ^
两个数值的每一位对齐,对应位只有一个 1 时才返回 1,都是 1 或都是 0,则返回 0
2.5 左移 <<
将数值的所有位向左移动指定位数
以
0来填充空位,以便得到完整的32位二进制数左移不会影响到符号位
2.6 有符号右移 >>
将数值向右移动指定位数
保留符号位
用符号位的数来填充所有空位,以便得到完整的值
2.7 无符号右移 >>>
以
0来填充空位对正数的有符号右移和无符号右移是一样的
对负数进行无符号右移会把负数的二进制码当成正数的二进制码,导致结果非常之大
3. 布尔操作符
3.1 逻辑非 !
应用于任何值,先将操作数转换成布尔值,再对其求反
规则:实际上先对操作数应用 Boolean() 转换为布尔值,然后再取反
同时使用两个逻辑非操作符,实际上就会模拟
Boolean()函数的行为,用于将一个值转换为与其对应的布尔值
3.2 逻辑与 &&
可以应用于各种类型的操作数,而不仅仅是布尔值
在有一个操作数不是布尔值时,就不一定返回布尔值了
规则:
第一个操作数不是布尔值,则使用
Boolean()进行转换,是布尔值,则直接判断结果为
true,则返回第二个操作数结果是
false,则返回第一个操作数。如果第一个操作数是
false,返回false如果第一个操作数是
null,返回null如果第一个操作数是
NaN,返回NaN如果第一个操作数是
undefined,返回undefined如果第一个操作数是
'',返回''如果第一个操作数是
0,返回0
短路操作:如果第一个操作数能够决定结果,那么就不会再对第二个操作数求值
var found = true;var result = (found && someUndefined);//发生错误alert(result);//这一行不会执行var found = false;var result = (found && someUndefined);//不会发生错误alert(result);//执行结果 false
回调函数:传值是函数时,让函数执行
function fn(callback) {//=> 如果传递的值是一个函数,我们让其执行// if(typeod callback === 'function') {// callback()// }callback && callback(); //=> 如果 callback 存在则执行它//=> 这种写法是不够严谨的,但是经常使用。因为约定好,默认 callback 要不然就传函数,要不然就不传。}fn(function() {})
3.3 逻辑或 ||
规则:
第一个操作数不是布尔值,则使用
Boolean()进行转换,是布尔值,则直接判断结果为
true,则返回第一个操作数结果是
false,则返回第二个操作数
短路操作:如果第一个操作数的求值结果为
true,那么就不会再对第二个操作数求值
赋值语句经常采用这种模式:用以给参数赋默认值
var myObject = preferredObject || backupObject;
虽然不够严谨,但是在真实项目中约定俗称,经常使用。因为默认要么不传值,要么传递的就是所需要的值。所以在需要传递的值为假的时候,应该避免这种默认值定义方式
4. 乘性操作符
在操作数为非数值的时候会执行自动类型转换,先使用 Number() 转型函数将其转换为数值
4.1 乘法 *
规则:
乘积超过数值的表示范围,则返回
Infinity或-Infinity有一个操作数是
NaN,则结果为NaNInfinity与0相乘,结果为NaNInfinity与非0数值相乘,结果为Infinity或-InfinityInfinity与Infinity相乘,结果为Infinity操作数不是数值,则在后台调用
Number()将其转换为数值,再应用上面的规则
4.2 除法 /
规则:
商超过数值的表示范围,则返回
Infinity或-Infinity有一个操作数是
NaN,则结果为NaNInfinity被Infinity除,结果为NaN非
0的有限数被0除,结果是Infinity或-InfinityInfinity被任何数值除,结果是Infinity或-Infinity操作数不是数值,则在后台调用
Number()将其转换为数值,再应用上面的规则
4.3 求模 %
求余数
规则:
都是数值,执行常规除法,返回除得的余数
被除数是
Infinity,除数是有限数值,结果返回NaN被除数是有限数值,除数是
0,结果是NaNInfinity被Infinity除,结果是NaN被除数是有限大的数值,除数是
Infinity,结果是被除数被除数是
0,结果是0操作数不是数值,则在后台调用
Number()将其转换为数值,再应用上面的规则
4.4 幂 **
幂运算符返回第一个操作数做底数,第二个操作数做指数的乘方。即 $ var1^{var2} $,其中 var1 和 var2 是其两个操作数。
幂运算符是右结合的。a ** b ** c 等同于 a ** (b ** c)。
包括 PHP 或 Python 等的大多数语言中,都包含幂运算符(一般来说符号是 ^ 或者 **)。这些语言中的幂运算符有着比其他的单目运算符(如一元 + 或一元 - )更高的优先级。但是作为例外,在 Bash 中,** 运算符被设计为比单目运算符优先级更低。在最新的 JavaScript(ES2016) 中,禁止使用带歧义的幂运算表达式。比如,底数前不能紧跟一元运算符(+/-/~/!/delete/void/typeof)
-2 ** 2;// 在 Bash 中等于 4 ,而在其他语言中一般等于 -4// 在 JavaScript 中是错误的,因为这会有歧义-(2 ** 2);// -4 在JavaScript中能够明显体现出作者的意图
示例
2 ** 3 // 83 ** 2 // 93 ** 2.5 // 15.58845726811989610 ** -1 // 0.1NaN ** 2 // NaN2 ** 3 ** 2 // 5122 ** (3 ** 2) // 512(2 ** 3) ** 2 // 64
如果要反转求幂表达式结果的符号,你可以采用这样的方式:
-(2 ** 2) // -4
强制求幂表达式的基数为负数:
(-2) ** 2 // 4
5. 加性操作符
5.1 加法 +
规则:
操作数是
NaN,返回NaNInfinity加Infinity,结果是Infinity-Infinity加-Infinity,结果是-InfinityInfinity加-Infinity,结果NaN操作数是字符串
都是字符串,进行拼接
只有一个是字符串,另一个转换为字符串,进行拼接
操作数是对象、数值、布尔值,调用
toString()方法取得相应的字符串值操作数是
undefined和null,调用String()函数取得字符串值
5.2 减法 -
规则:
操作数是
NaN,返回NaNInfinity减Infinity,结果是NaN-Infinity加-Infinity,结果是NaNInfinity加-Infinity,结果Infinity-Infinity加Infinity,结果-Infinity操作数是字符串、布尔值、
null、undefined,先在后台调用Number()函数转换为数值,在按上面规则执行操作数是对象,调用对象的
valueOf()方法取得对象的数值,如果结果是NaN,则减法的结果是NaN。如果没有valueOf()方法,则调用其toString()方法将其得到的字符串转换为数值
6. 关系操作符
关系操作符有:<、>、<=、>=
规则:
两个数都是数值,则执行数值的比较
都是字符串,比较两个字符串对应的字符编码值
一个是数值,则将另一个也转换为数值,执行比较
一个是对象,调用对象的
valueOf()方法取得对象的数值,如果没有valueOf()方法,则调用其toString()方法将其得到的字符串转换为数值布尔值,将其转换为数值执行比较
操作数存在
NaN或者undefined、null,结果都是false
7. 相等操作符
7.1 相等与不相等 ==
规则:
先转换后比较
布尔值,转换为数值再比较
一个字符串,一个数值,则将字符串转换为数值再比较
都是字符串,比较两个字符串对应的字符编码值
一个是对象,另一个是字符串,则将对象转换为字符串再比较
都是对象,则比较是不是同一对象,如果指向同一对象,则相等返回
true其他都是转换为数值再比较
null和undefined是相等的有
NaN,使用相等结果都是false,使用不相等结果都是true,NaN不等于任何值,包括自身
1==true //=> true1==false //=> false2==true //=> false[] == 0 //=> true,都转换为数字[] == '0' //=> false,左边转换为字符串 '',再比较{} == '[object Object]' //=> true,左边先转换为字符串,再比较[]==false //=> true,都转换为数字[]==true //=> false,都转换为数字![]==false //=> true,先算 ![] 为 false,再比较![]==true //=> false,先算 ![] 为 false,再比较
7.2 全等和不全等 ===
只在两个操作数未经转换就相等的情况下才返回 true,也就是类型和值都要相等。真实项目中为了保证代码的严谨性,应该更多的使用严格相等。
8. 条件、赋值、逗号
8.1 条件操作符 ? :
variable = boolean_expression ? true_value : false_value
可以执行多条语句,用小括号包裹,不同语句用逗号隔开;也可以不执行任何语句,用 null undefined等占位
var num = 12;num > 10 ? (num++, num*=10) : null;
8.2 赋值操作符 =
简单的赋值操作符由等号表示,如果在等号前面再添加乘性操作符、加性操作符或位操作符,就变成了复合操作符。
*=
/=
%=
+=
-=
<<=
=
=
设计这些操作符的主要目的是简化赋值操作,使用它们不会带来任何性能的提升。
8.2 逗号操作符,
使用逗号操作符可以在一条语句中执行多个操作
var num = 1, num2 = 2, num3 = 3;
多用于声明多个变量,但除此之外,还可以用于赋值,在用于赋值时,逗号操作符总会返回表达式中的最后一项。
var num = (5, 1, 4, 0); //=> num: 0
在三元运算符中,也可以使用逗号来分隔多条语句
