1.JavaScript规定了几种语言类型
JS包括7种数据类型,其中有分为原始类型和引用类型。
原始类型
Null: 只包含一个值nullUndefined: 只包含一个值undrfinedNumber: 整数和浮点数,还有一些特殊值(-Infinity、+Infinity和NaN)Boolean: 包含两个值true和falseString: 一串表示文本值的字符序列Symbol: 一种实例是唯一且不可改变的数据类型
引用类型
Object、Array、Function
2.JavaScript对象的底层数据结构是什么
- 原始类型直接存储在栈中,每种类型数据占用的内存空间大小时确定的,并由系统自动分配和自动释放;
- 引用类型会被存储在堆中,准确来说,引用类型的值实际存储在堆内存中,他在栈中只存储了一个固定长度的地址,这个地址指向堆内存的值。
- 数据在内存中的存储结构,也叫物理结构,分为两种:顺序存储结构和链式存储结构:
- 顺序存储结构 : 是把数据元素存放在地址连续的存储单元里,其数据见的逻辑关系和物理关系是一致的。数组就是其中的代表。
- 链式存储结构:是把数据元素存放在任意的存储单元里,这些数据在内存中的位置有可能是连续的,也有可能不不连续的,链表就是其中的代表。
- 形象地说,就是去银行取钱,顺序存储结构就是客户按照先来后到坐在标有顺序的座椅上,等候办理业务;链式存储结构就是客户拿着叫号机给的编号,然后随意地坐在没有顺序的座椅上,等候叫号办理业务。
3.null和undefined的区别
null: 表示被赋值过的对象,刻意把一个对象赋值为null,表示该值为空,不应该有值。转换数值时的值为0;undefined: 表示缺少值,在对象初始化的时候未进行赋值定义。转换数值时的值为NaN
4.至少可以说出三种判断JavaScript数据类型的方式,以及他们的优缺点,如何准确的判断数组类型
| 类型 | 优点 | 缺点 |
|---|---|---|
typeof |
能准确判断一个变量是否为原始类型 | 判断引用类型时略显乏力,除了函数判断为function外,其他都判断为object |
instanceof |
能判断引用类型的具体是什么类型对象 | |
toString |
利用Object对象的继承性,toString()返回[object type],其中type是对象的类型 |
如果此方法在自定义对象中未被覆盖,toString才会达到预想的效果,事实上,大部分引用类型比如Array、Date、RegExp等都重写了toString方法。 |
5.类型转换
因为JS是弱类型语言,所以类型转换会经常发生。类型转换分两种:隐式转换即程序自动进行的类型转换,强制转换即我们手动进行的类型转换。
类型转换规则
| 转换前类型 | 转换前值 | 转换后(Boolean) | 转换后(Number) | 转换后(String) |
|---|---|---|---|---|
Boolean |
true |
- | 1 |
true |
Boolean |
false |
- | 0 |
false |
Number |
123 |
true |
- | 123 |
Number |
Infinity |
true |
- | Infinity |
Number |
0 |
false |
- | 0 |
Number |
NaN |
false |
- | NaN |
String |
‘ ’ | false |
0 |
- |
String |
123 |
true |
123 |
- |
String |
123lyichao |
true |
NaN |
- |
String |
lyichao |
true |
NaN |
- |
Symbol |
Symbol() |
true |
TypeError |
TypeError |
Null |
null |
false |
0 |
null |
Undefined |
undefined |
false |
NaN |
undefined |
Function |
function(){} |
true |
NaN |
function(){} |
Object |
{} |
true |
NaN |
[object Object] |
Array |
[] |
true |
0 |
`` |
Array |
["lyichao"] |
true |
NaN |
lyichao |
Array |
["123","lyichao"] |
true |
NaN |
123,lyichao |
if语句和逻辑语句
在if语句和逻辑语句中,如果只有单个变量,会先讲变量转换成Boolean,只有下面几种情况会转换成false,其他都会被转换成true
1 | |
各种数学运算符
我们在对各种非Number类型运用数学运算符(- * /)时,会先讲非Number类型转换为Number类型
1 | |
⚠️注意!加法是个例外,执行加法运算时:
- 1.当一侧为
String类型时,会被识别为字符串拼接,并会优先将另一侧转换为字符串类型; - 2.当一侧为
Number类型,另一侧为原始类型,则将原始类型转换为Number类型; - 3.当一侧为
Number类型,另一侧为引用类型,则将引用类型和Number类型转换成字符串后拼接。
1 | |
==
使用==时,若两侧类型相同,则比较结果和=== 相同,否则会发生隐式转换。使用==时会发生转换可以分为几种情况(只考虑两侧类型不同时):
-
NaN
NaN和其他任何类型比较永远返回false(包括和他自己)。1
NaN == NaN // false -
Boolean
Boolean和其他任何类型比较,Boolean首先被转换为Number类型。1
2
3
4true == 1 // true true == '2' // false true == ['1'] // true true == ['2'] // false这里注意一个可能会弄混的点:
undefined、null和Boolean比较,虽然undefined、null和false都很容易被想象成假值,但是他们比较结果是false,原因是false首先被转换成0:1
2undefined == false // false null == false // false -
String和Number
String和Number比较,先将String转换为Number类型。1
2123 == '123' // true '' == 0 // true -
null和undefined
null == undefined比较结果是true,除此之外,null、undefined和其他任何结果的比较值都为false。1
2
3
4
5
6
7null == undefined // true null == '' // false null == 0 // false null == false // false undefined == '' // false undefined == 0 // false undefined == false // false -
原始类型和引用类型
当原始类型和引用类型做比较时,对象类型会依照
ToPrimitive规则转换为原始类型:1
2'[object Object]' == {} // true '1,2,3' == [1, 2, 3] // true来看看下面这个比较:
1
[] == ![] // true!的优先级高于==,![]首先会被转换为false,然后根据上面第三点,false转换成Number类型0,左侧[]转换为0,两侧比较相等。1
2[null] == false // true [undefined] == false // true根据数组的
ToPrimitive规则,数组元素为null或undefined时,该元素被当做空字符串处理,所以[null]、[undefined]都会被转换为0。所以,说了这么多,推荐使用
===来判断两个值是否相等…
为什么0.1+0.2!==0.3
首先先来看下简单的函数计算
1 | |

为什么会出现这种情况呢?原因就是出现了精度丢失。
计算机中所有的数据都是以二进制存储的,所以在计算时计算机要把数据先转换成二进制进行计算,然后在把计算结果转换成十进制。
由上面的代码不难看出,在计算0.1+0.2时,二进制计算发生了精度丢失,导致再转换成十进制后和预计的结果不符。