前言
JavaScript
作为一门弱类型
的语言,即里面的变量的类型不是固定的。所以在JS里面类型转换发生的非常频繁。 本文梳理了以下知识点,希望能帮助到大家。
类型转换
JS类型转换大体分为两种:
隐式转换
:说明白点就是程序会自动进行的类型转换强制转换
:即调用一些方法来实现类型转换
隐式转换
字符串加法运算
任何类型的数据和字符串类型的数据进行加法操作时,其他数据类型会自动转换为字符串类型,此时的+
不是数学意义,是字符串拼接。
var result=“hello” + “ world” //结果为“hello world string
var result=“1”+1 //结果为 “11”
var result=“1”+ true // 结果为 “1true”
var result=“1”+ undefined //结果为 “1undefined”
var result=“1”+ null // 结果为 “1null ”
字符串其他运算
任何数据类型和字符串类型进行加法以外的运算(-
*
/
),字符串要先转换为数字再去进行运算
- 如果字符串为
纯数字
,则转换为相应的数字
1-"11" // -10
- 如果字符串中存在字符串以外的字符,则转换为NaN,NaN和任何数据类型运算都是NaN。
1-"11a" // NaN
非字符串运算
除了字符串以外的数据,在进行运算(-
*
/
)先转换为数字,再进行运算:
原数据 | 转换后 |
---|---|
true | 1 |
false | 0 |
null | 0 |
undefined | NaN |
1-true // 0
1-false // 1
1- null // 1
1-undefined // NaN
在非字符串
运算中,+
也是比较特殊的:
- 当有一侧为
数字
时,其他数据为简单数据类型,则简单数据类型转换为数字类型 - 当有一侧为
引用类型
,其他数据为任意类型,则将引用类型和其他数据均转换为字符串并
进行拼接
1 + null // 1
1+ true // 2
1+ {} // 1[object Object]
true+{} //true[object Object]
逻辑运算
在if
语句和逻辑语句中,如果只有单个变量,会将其转换为Boolean值:
Number
类型中:0 转换为 false;NaN转换为false字符串
类型中:“”空字符串转换为falsenull
:转换为falseundefined
:转换为falseobject
:[]、{}、function(){} 等都转换为true
== 和 ===
==
和 ===
的区别:当 ==
两侧的类型相同时,比较结果与 ===
相同。因为==
比较时会发生隐式转换,而===
是恒等于,不仅内容相等而且数据类型一致。
==
比较时发生的类型转换:
-
NaN
只要存在NaN,则结果就为false(它和自己也不相等) -
null和undefined
把这两个放一起是因为 null==undefined 结果为true,此外,null、undefined和其他任何类型的结果都为false。 -
简单数据类型和复杂数据类型:
当简单数据类型和复杂数据类型进行比较时,复杂数据类型会依照ToPrimitive
规则转换为简单数据类型:
"[object Object]"=={} //true
'1,2,3'==[1,2,3] //true
来看下面的例子:
[null]==false //true
[undefined]==false //true
根据数组的ToPrimitive
规则,数组元素为null
或者undefined
时,该元素被当做空字符串
处理,所以 [null]、[undefined]都转换为0
强制转换
-
Boolean()
其他数据类型转换为布尔值:
Number
:非0即真字符串
:非空即真null
、undefined
为false- []、{}、function()等为true
-
Number()
其他数据类型转换为数字:
Boolean
:true为1,false为0字符串
:当字符串里面全是数字时,可以转换,其他转换为NaNnull
为0,undefined
为NaN- [] 为 0; function(){}、{}为NaN
-
parseInt()
对数字取整数:
- 字符串:parseInt(“100a”) 结果为100; parseInt("10a1b) 结果为10; 如果开头不为数字,则为NaN
- 把其他进制转换为十进制,必须传入字符串 parseInt(“1000”,2) 结果为8
-
parseFloat()
对数字取浮点数
-
toString()
其他数据类型转换为字符串
特殊的类型转换
在ECMAScript中规定,引用类型是一种数据结构
,将数据和功能整合在一起。
我们平时所说的对象,其实就是某个引用类型的实例,这些引用类型可以是自定义的,也有特定的,例如:
Array
数组Date
日期RegExp
正则Function
函数
包装类型
在JavaScript中,为了方便操作基本类型、简化数据操作。ECMAscript还提供了几个特殊的引用类型,他们是简单数据类型的包装类型
:
- Boolean
- Number
- String
包装类型和简单数据类型之间的转换也是一种
特殊的类型转换
。
包装类型和简单数据类型的区别
true===new Boolean(true); //false
1===new Number(1) //false
'123'===new String('123'); //false
console.log(typeof new Number(1)) //object
console.log(typeof 1) // number
以上是数据类型的区别。
他们的主要区别在于
生存周期
不同。用new
关键字创建的引用类型的实例,在执行流离开当前作用域之前一直都保存在内存中,而简单数据类型只存在这行代码执行的瞬间,然后立即被销毁,这就意味着我们不能为简单数据类型添加属性和方法。
装箱和拆箱
幸好,JavaScript中的装箱拆箱机制使我们操作简单数据类型更方便。
先简单看一下装箱和拆箱的概念:
- 装箱操作:把简单数据类型转换为对应的包装类型
- 拆箱操作:把引用类型转换为简单数据类型
var str="hello";
var str1=str.substr(0,2);
我们刚刚说了,简单数据类型没有方法和属性,为什么上面代码能正确执行呢?
实际上发生了以下过程:
- 创建一个String包装类型
实例
- 在实例上调用substr方法
- 销毁实例
也就是说,我们在使用简单数据类型调用方法和属性时,会自动发生装箱和拆箱操作。
下面我们再讨论一下拆箱的具体过程。
从引用类型到简单数据类型,会遵循ECMAScript规定的toPrimitive
原则,一般会调用引用类型的valueOf
和toString
方法。 引用类型转换为不同简单数据类型时遵循的原则不同:
- 引用类型转换为
Number
类型时,先调用valueOf
,再调用toString
- 引用类型转换为
String
类型,先调用toString
,再调用valueOf
如果
valueOf
和toString
都不存在,或者重写方法没有返回简单数据类型,都会抛出typeError
异常。
var obj1={
valueOf: function(){
return 1;
},
toString: function(){
return "123";
}
}
console.log(obj1-1) //0
console.log(obj+"456") //"123456"
var obj2={
valueOf: function(){
console.log('valueOf');
return {};
},
toString: function(){
console.log('toString');
return {};
}
}
console.log(obj2-1) //valuseOf TypeError
除了程序中的自动装箱和拆箱外,我们可以手动进行操作。我们可以通过new
关键字实现装箱操作, 直接调用包装类型的valueOf
或者toString
,实现拆箱操作。
最后
本人也是第一次写笔记,文笔比较差,写这篇文章耗费的时间出乎我的意料,不过收获还是不错的。整理在CSDN上的目的:一是帮助同在学习前端的小伙伴,二是希望大家指出我的不足,一起进步。
以后的各类笔记我都会一一整理,希望在梳理知识的同时帮助大家快速掌握知识。
参考资料
https://juejin.cn/post/6844903854882947080