谈谈你对JavaScript数据类型的见解

image.png

导读

每一种语言都有它的数据类型,学习一门语言要先掌握好它的数据类型。数据类型就好比,我们要搭建一个建筑物,就需要的各种类型的材料。如何将各种材料合理配合使用,搭建出最合理最稳固的建筑物?这就需要我们明白每一种材料适用于什么地方,有什么优缺点,能否相互转换…

当面试官问了你以下几个问题,你会怎么回答呢?能够清晰表示的朋友们,无需浪费宝贵的时间。当然也希望大家可以在评论区补充指正!

  1. 为什么数据按照原始值类型和对象类型分类?(栈内存、堆内存)
  2. 为什么typeof null的判断结果是Object? (typeof判断机制)
  3. 为什么undefined==null是true,说说undefined与null的区别?(undefined、null)
  4. 为什么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。
image.png

undefined与null都可以用来表示空,而在一门语言中一个概念往往只需要一种表达即可(当然也可以有近义词,难不成js也存在近义词之说?😨)。上面说到null的类型是一个bug,那么undefined与null都可以用表述空这个概念,那为什么js要用两个表达式表达一个相同的概念呢?难不成这又是一个bug?🤔

其实,根据语言的特性,如java属于一种静态类型语言,类型是固定的,如果存在一个不存在的成员,那么编译器直接编译失败,所以只能有null表示空值。而js属于动态编译语言,编译初期并不知道类型是否存在,类型不存在也可以编译通过,只有在运行期间才知道是否存在,所以就需要一个类型表示此种情况,这个类型就是undefined。

因此,在js中undefined与null还有有区别的:

  • undefined:属于全局对象的一个属性,也就是全局作用域的一个变量。表示一个变量没有定义,属于隐藏式空值。
  • null:属于字面量,表示缺少的标识,指示变量未指向任何对象。表示一个变量定义了,但是没有指向任何内存中的对象,属于申明式空值。

比如,有两种情况可以表示没有水,一种是一个水杯中没有水,另一种是连水杯都没有。都可以表示没水。水杯中没有水就好比undefined,定义了水杯这个容器(变量),但是没有装水(赋值)。没有水杯好比null,就没有定义水杯容器(变量)。

image.png

三、 Number

1、为什么0.1 + 0.2 !== 0.3 ?

这是一道小学生算数题,口算就可以直接得出结果。但是对于计算机而言,却是一个否命题。这是因为在生活中,数字与数字之间采用的是十进制的运算。而在计算机中,所有的数据都是以二进制值的形式存储的(上文问题1中也有提及)。那么在运算过程中,自然采用的是二进制的运算

运算过程:首先在计算机中,我们看到的数据都是计算机处理后展示在我们面前的。所以在计算前,需要将数据先转成二进制形式,然后再进行二进制计算。最后再将计算的结果转成十进制形式展示出来。

image.png

二进制计算:对位处理,从最低位开始,逢二进一
二进制转十进制:从小数点开始往左数第一位数称为第0位,而这第0位则是用来计算权的几次方的,往左依次+1数过去,而小数点的右边则是负位,小数点右边第一位是第-1位越往右数依次-1。最后将每一位数字乘以对应的权次方累加得到的结果就是十进制数

精度丢失:0.1+0.2二进制相加的结果再转成十进制是0.30000000000000004,而0.3的二进制转成十进制是0.3,这就导致了0.1+0.2不等于0.3。

其实对于二进制表示法还有更深一步的解释,感兴趣的朋友们可以去搜索IEEE754标准,其中二进制表示法包含符号位、指数位、尾数位。🐂🐂🐂

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值