导读
每一种语言都有它的数据类型,学习一门语言要先掌握好它的数据类型。数据类型就好比,我们要搭建一个建筑物,就需要的各种类型的材料。如何将各种材料合理配合使用,搭建出最合理最稳固的建筑物?这就需要我们明白每一种材料适用于什么地方,有什么优缺点,能否相互转换…
当面试官问了你以下几个问题,你会怎么回答呢?能够清晰表示的朋友们,无需浪费宝贵的时间。当然也希望大家可以在评论区补充指正!
- 为什么数据按照原始值类型和对象类型分类?(栈内存、堆内存)
- 为什么typeof null的判断结果是Object? (typeof判断机制)
- 为什么undefined==null是true,说说undefined与null的区别?(undefined、null)
- 为什么0.1 + 0.2 !== 0.3 ?(数据精度)
ps:括号内为涉及的知识点
一、类型分类
按照开发过程中使用频率排序,目前项目基本上没有用到symbol和bigint类型。
原始值类型(基本类型)
- string 字符串
- boolean 布尔值
- undefined 未定义
- number 数值
- null 空对象指针
- symbol 唯一值
- bigint 大数
对象类型(引用类型) - 可调用/执行对象:function 函数
- 标准普通对象:Object
- 标准特殊对象:Array 数组、RegExp 正则、Date 日期、Math、Error……
- 非标准特殊对象:Number、String、Boolean……
1. 为什么数据按照原始值类型和对象类型分类?
从名字出发,对象类型听起来可能比较抽象,但是原始值类型顾名思义,就是固定值即保持原始值不变的类型。(瞎说的,非常的不专业😂)
咳咳咳,正经的来了!
- 从内存空间角度而言
在js中每一个变量在内存中都需要一个空间进行存储,内存空间有两种,栈内存和堆内存。原始类型的值存储在栈内存中,分配了固定的空间大小,自然存储在其中的变量就不可变了;而对象类型的值存储在堆内存中,动态分配空间大小,存储在其中的变量也就可以改变啦。
关于栈内存和堆内存的相关概念,打算后续单独总结一篇文章
二、null与Object
1. 为什么typeof null的判断结果是Object?
所有数据类型在计算机底层都是按照64/32位2进制值进行存储的,而typeof是按照二进制值的前三位进行类型判断的。
二进制前三位是0表示是对象类型,二进制全是0表示是null类型,全是0自然包括前三位是0,因此null进行typeof判断是也属于对象。那么这样不就产生歧义了吗,确实这其实是一个历史遗留问题,算是一个bug。
- 当二进制前三是0时,根据是否实现call方法,可以判断funciton类型,若实现了该方法则是function类型。
- 整数:1;浮点数:010;字符串:100;布尔类型: 110;undefined:-2^30;
其余类型对应的二进制数,欢迎知道的朋友们补充👏
2. 为什么undefined==null是true,说说undefined与null的区别?
==相等运算符,在进行比较之前会进行类型转换,转换成相同数据类型后再进行比较。由图可知undefined与null转程布尔值都为false,自然相等运算符结果为true。
undefined与null都可以用来表示空,而在一门语言中一个概念往往只需要一种表达即可(当然也可以有近义词,难不成js也存在近义词之说?😨)。上面说到null的类型是一个bug,那么undefined与null都可以用表述空这个概念,那为什么js要用两个表达式表达一个相同的概念呢?难不成这又是一个bug?🤔
其实,根据语言的特性,如java属于一种静态类型语言,类型是固定的,如果存在一个不存在的成员,那么编译器直接编译失败,所以只能有null表示空值。而js属于动态编译语言,编译初期并不知道类型是否存在,类型不存在也可以编译通过,只有在运行期间才知道是否存在,所以就需要一个类型表示此种情况,这个类型就是undefined。
因此,在js中undefined与null还有有区别的:
- undefined:属于全局对象的一个属性,也就是全局作用域的一个变量。表示一个变量没有定义,属于隐藏式空值。
- null:属于字面量,表示缺少的标识,指示变量未指向任何对象。表示一个变量定义了,但是没有指向任何内存中的对象,属于申明式空值。
比如,有两种情况可以表示没有水,一种是一个水杯中没有水,另一种是连水杯都没有。都可以表示没水。水杯中没有水就好比undefined,定义了水杯这个容器(变量),但是没有装水(赋值)。没有水杯好比null,就没有定义水杯容器(变量)。
三、 Number
1、为什么0.1 + 0.2 !== 0.3 ?
这是一道小学生算数题,口算就可以直接得出结果。但是对于计算机而言,却是一个否命题。这是因为在生活中,数字与数字之间采用的是十进制的运算。而在计算机中,所有的数据都是以二进制值的形式存储的(上文问题1中也有提及)。那么在运算过程中,自然采用的是二进制的运算。
运算过程:首先在计算机中,我们看到的数据都是计算机处理后展示在我们面前的。所以在计算前,需要将数据先转成二进制形式,然后再进行二进制计算。最后再将计算的结果转成十进制形式展示出来。
二进制计算:对位处理,从最低位开始,逢二进一。
二进制转十进制:从小数点开始往左数第一位数称为第0位,而这第0位则是用来计算权的几次方的,往左依次+1数过去,而小数点的右边则是负位,小数点右边第一位是第-1位越往右数依次-1。最后将每一位数字乘以对应的权次方累加得到的结果就是十进制数
精度丢失:0.1+0.2二进制相加的结果再转成十进制是0.30000000000000004,而0.3的二进制转成十进制是0.3,这就导致了0.1+0.2不等于0.3。
其实对于二进制表示法还有更深一步的解释,感兴趣的朋友们可以去搜索IEEE754标准,其中二进制表示法包含符号位、指数位、尾数位。🐂🐂🐂