弱类型的JS隐式转换
# 弱类型的JS隐式转换
参考文献:从++[[]][+[]]+[+[]]==10?深入浅出弱类型JS的隐式转换 (opens new window)
[TOC]
# 一、强弱类型
- 强类型
- 每个变量和对象都必须具有声明类型,他们是在编译的时候就确定类型的数据,在执行时类型不能更改。
- 弱类型
- 在执行的时候才会确定类型。
- 强类型安全,而且效率高。弱类型相比而言不安全 ,但它让不正确的类型可以通过隐式转换得到正确类型,就好像所有运算能进行运算一样。
# 二、ECMAScript 运算符优先级
运算符 | 描述 |
---|---|
. [] () | 字段访问、数组下标、函数调用以及表达式分组 |
++ -- - + ~ ! delete new typeof void | 一元运算符、返回数据类型、对象创建、未定义值 |
* / % | 乘法、除法、取模 |
+ - + | 加法、减法、字符串连接 |
<< >> >>> | 移位 |
< <= > >= instanceof | 小于、小于等于、大于、大于等于、instanceof |
== != === !== | 等于、不等于、严格相等、非严格相等 |
& | 按位与 |
^ | 按位异或 |
&& | 逻辑与 |
?: | 条件 |
= oP= | 赋值、运算赋值 |
, | 多重求值 |
# 2.1一元运算符
一元运算符只有一个参数,即要操作的对象或值。它们是 ECMAScript 中最简单的运算符。
# 2.1.1一元 + 和一元 - 运算符
将操作数转换为Number类型,其中一元-运算符还会反转其正负(如果操作符为NaN,仍为NaN。
+true // 1 +false // 0
1
2计算字符串的方式与 parseInt() 相似,主要的不同是只有对以 "0x" 开头的字符串(表示十六进制数字),一元运算符才能把它转换成十进制的值
- 用一元加法转换 "010",得到的总是 10,而 "0xB" 将被转换成 11。
# 2.1.2++前增量运算符
数值上+1。
# 2.2+ - 运算符
# 2.2.1+ 运算符
- 特殊行为
- 某个运算数是 NaN,那么结果为 NaN。
- -Infinity 加 -Infinity,结果为 -Infinity。
- Infinity 加 -Infinity,结果为 NaN。
- +0 加 +0,结果为 +0。
- -0 加 +0,结果为 +0。
- -0 加 -0,结果为 -0。
- ECMAScripts5规范 (opens new window):如果只有一个运算数是字符串,把另一个运算数转换成字符串,结果是两个字符串连接成的字符串。
1+"1" //"11"
"1"+1 //"11"
"1"+"1" //"11"
2
3
- 转数值:只对null、''、false、数值字符串有效。
const num1 = +null;
const num2 = +"";
const num3 = +false;
const num4 = +"169";
// num1 num2 num3 num4 => 0 0 0 169
2
3
4
5
# 2.2.2- 运算符
- 特殊行为
- 某个运算数是 NaN,那么结果为 NaN。
- Infinity 减 Infinity,结果为 NaN。
- -Infinity 减 -Infinity,结果为 NaN。
- Infinity 减 -Infinity,结果为 Infinity。
- -Infinity 减 Infinity,结果为 -Infinity。
- +0 减 +0,结果为 +0。
- -0 减 -0,结果为 -0。
- +0 减 -0,结果为 +0。
- 某个运算符不是数字,那么结果为 NaN。
- 规范:如果有一个不是数字,会调用 ToNumber 方法按照规则转化成数字类型,然后进行相减。
# 2.3 类型转换
# 2.3.1 显式类型转换(强制类型转换)
Number()
parseInt() 可以用来去掉px
parseFloat()
# 2.3.2 隐式类型转换
参考教程:你所忽略的js隐式转换 (opens new window)
- 将值转为原始值,
ToPrimitive()
- 将值转为数字,
ToNumber()
- 将值转为字符串,
ToString()
+
200 + '3' 变成字符串- * / %
'200' - 3 变成数字'1' * 1 // 1 'a' * 1 // NaN null * 1 // 0 null的二进制表示都是0 undefined * 1 // NaN
1
2
3
4++ --
变成数字> <
数字的比较 、字符串的比较(Object遇到> <
会转换成字符串比较)!
取反 把右边的数据类型转成布尔值
let a = 3;
let b = new Number(3);
console.log(a == b); // true
console.log(a === b); // false
2
3
4
5
new Number()
是一个内置的函数构造函数。 虽然它看起来像一个数字,但它并不是一个真正的数字:它有一堆额外的功能,是一个对象。
当我们使用==
运算符时,==
会引发隐式类型转换,右侧的对象类型会自动拆箱为Number
类型,返回true
。
a=?
if(a==1 && a==2 && a==3){
console.log(1)
}
// answer1
const a = {
num1: 0,
valueOf() {
return this.num1 += 1
}
};
// answer2
let a = [1,2,3]
a.toString = a.shift
// or
a.join = a.shift
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 2.3.2.1 布尔值转数值
# 2.3.2.2 字符串和数字,字符串转数字
# 2.3.2.3 对象,优先用valueOf(),其次toString()
# 严格比较运算符
===
与比较运算符==
的区别
对于关系运算符(比如 <=)来说,会先将操作数转为原始值,使它们类型相同,再进行比较运算。
== 执行类型转换的规则如下:(数字>字符串>对象)
如果一个运算数是 Boolean 值,在检查相等性之前,把它转换成数字值。false 转换成 0,true 为 1。
如果一个运算数是字符串,另一个是数字,在检查相等性之前,要尝试把字符串转换成数字。
如果一个运算数是对象,另一个是字符串,在检查相等性之前,要尝试把对象转换成字符串。
如果一个运算数是对象,另一个是数字,在检查相等性之前,要尝试把对象转换成数字。