JS数据类型转换
9种数据类型区别及相互转换
数据类型分类
- 基本数据类型
number string boolean null undefined symbol bigint - 引用数据类型
object function - isNaN、NaN、Infinity
把其他数据类型转换成Number
的规则
转换方法
- Number([val])
- parseInt/parseFloat([val])
隐式类型转换 浏览器内部默认Number
转换再进行计算的
- boolean 转为数字 1 或 0
- null 转为数字 0
- 空字符串
""
转化为数字为0 - undefined 转为数字类型
NaN
,任何一个数加上NaN
都等于NaN
- 字符串中只要出现一个非数字都将转换为
NaN
,例如"12px"
parseInt/parseFloat 机制
- 从左侧第一个字符开始,查找有效数字,遇到非有效数字则停止查找
- 遇到如果第一个就是是非有效数字则直接转化为
NaN
- 如果找不到有效字符,仍然返回
NaN
- parseFloat 比 parseInt 多识别一个小数点
- 都是先把要转换的值转换为字符串
parseInt("")
Number("")
isNaN("")
parseInt(null)
Number(null)
isNaN(null)
parseInt("12px")
Number("12px")
isNaN("12px")
parseFloat("1.6px")+parseInt("1.2px")+typeof parseInt(null)
isNaN(Number(!!Number(parseInt("0.8"))))
typeof !parseInt(null) + !isNaN(null)
把其他数据类型转换成String
的规则
方法
- toString()
- String()
隐式 一般调用的是toString
- 一般都是直接使用
""
包起来,只有{}
普通对象调取toString
是调取的Object.prototype.toString
,这个原型上的toString不是转化为字符串,而是检测数据类型,返回[object Object]
+
号左右有一边出现字符串或者对象,就会按照字符串来拼接
对象 + 0
首先是把对象转换为字符串[object Object]
,再将字符串转换为数字
所以对象最终也会变成字符串拼接[]
转为字符串将调用原型链中的toString
方法变为空字符串""
把其他类型转换为boolean的规则
规则
- 只有
0、NaN、null、undefined、空字符串
五个值会变为布尔的false
,其余都是true
- 显式
- ! 转换为布尔值后取反
- !! 转换为布尔类型
- Boolean([val])
- 隐式
- 在循环或者条件判断中,条件处理的结果就是布尔类型值
== 的转换规则
- 类型一样时,对象比较的是堆内存的地址
{}=={}
:false[]==[]
:falseNaN==NaN
:: false
- 类型不一样时
- 只有
null==undefined
为true
,然后null/undefined
和其他任何数据类型值都不相等
- 字符串==对象,要把对象转换为字符串
- 如果==两边数据类型不一致,那两边都是需要转换成数字再做比较
- 只有
题目
[] == false
![] == false
过程
[]
转为空字符串""
再转为数字0
,false
直接转为数字0![]
把[]
转为boolean
类型再取反false
,false
再转换为数字0- 所以两个答案都是true
+ 号 的转换规则
let n = "10";
++n // 11
+n // 10
{}+0 // 0
左边的{}被当做代码块,不参与运算
运算只处理 + 0
({})+0 // [object object]0
0+{} // 0[object object]
一定为数学运算
+{} // NaN
以上情况是最终转为数字的数学运算
运算符优先级
对象属性的调用
对象数据类型:由零到多组键值对(属性名和属性值)组成的
属性名的类型
- 说法一:属性名类型只能是字符串或者Symbol
- 说法二:属性名类型可以是任何基本类型值,处理中可以和字符串互通
但是属性名绝对不能是引用数据类型,如果设置引用类型,最后也是转换为字符串[object Object.]
处理的
let x = {
0: 0
};
let y = {
1: 1
};
let obj = {
0: 12,
true: 'xxx',
null: 20
};
// 会把对象变为字符串作为属性名
obj[x] = 100; //=> obj['[object Object]']=100
obj[y] = 200
题目
综合题
let res = 100 + true + 21.2 + null + undefined + "Tencent" + [] + null + 9 + false
console.log(res)
打印
NaNTencentnull9false
拆分一下
求下列题内容输出
let result = 100 + true + 21.2 + null + undefined + "Tencent" + [] + null + 9 + false;
console.log(result); // NaNTencentnull9false
console.log([]==false);// true
console.log(![]==false);// true
设置一个变量a,使得if语句能够执行
var a = ?;
if (a == 1 && a == 2 && a == 3) {
console.log(1);
}
方式一:将a设置为一个对象,并自定义一个toString
方法
因为隐式类型转换,==
时会将对象a转为字符串再转为数字类型,过程中会调用到对象原型链中的toString
方法
var a = {
i: 0,
toString() {
return ++this.i
}
}
if (a == 1 && a == 2 & a == 3) {
console.log(1)
}
方法二:使用Object.definedProperty
(或者Proxy)数据拦截再处理
拦截到获取a的时候,按对应次数返回1,2,3
var i = 0;
Object.defineProperty(window, "a", {
get() {
return ++i;
}
})
if (a == 1 && a == 2 & a == 3) {
console.log(1)
}
parseInt题目
[1,2,3].map(parseInt) // 1, NaN, NaN
- parseInt([value]) 把value转换为数字(内核机制:需要把value先变为字符串,然后从字符串左侧第一个字符查找,把找到的有效数字字符转换为数字,直到遇到一个非有效数字字符为止)
parseInt([value],[n])
把[value]
看做[n]
进制的数据,最后转换为十进制- [n]不写:默认是10。特殊情况字符串是以
0X
开头,默认值是16进制
- [n]范围 2~36之间 不在这个之间的 除了0和10是一样的,剩下结果都是NaN
- [n]不写:默认是10。特殊情况字符串是以
补全一下代码
[1,2,3].map((item, index) => {
return parseInt(item, index);
})
parseInt(1, 0) // 把1当做10进制,转为10进制
parseInt(2, 1) // 把2当做1进制,没有在2-36之间,所以转为NaN
parseInt(3, 2) // 把3当做2进制,转为10进制,但是2进制只有1,0符合,所以为NaN
// 1, NaN, NaN
其他进制转换
小于n进制的非负整数都满足n进制
三进制
parseInt(25, 3);
只有2
满足3进制,所以实际上是
parseInt("2", 3);
// 2*3^0 = 2
四进制
parseInt(23, 4) // 2和3都满足4进制
parseInt("23", 4)
// 3*4^0 + 2*4^1 = 3 + 8 = 11;
let a = {n: 1};
let b = a;
a.x = a = {n: 2};
console.log(a.x);
console.log(b);