【JS之路】“简单”的数据类型

JavaScript数据类型

ECMAScript规定了8种数据类型,又分为两种:简单数据类型复杂数据类型

简单数据类型

  • Number:整数或者浮点数(里面还包括一些特殊值,例如:Infinity 代表无穷大,-Infinity 代表无穷小,NaN(not a number))
  • Boolean:只包含两个值 true和false
  • 字符串:用单引号或者双引号包裹起来的都叫字符串
  • underfined:未定义的
  • null:空

在ES6+中加入了SymbolBigInt(本文暂不作讨论)

复杂数据类型:

  • object:对象类型,平时用的包括ObjectFunctionArrayMathDate等都是特殊的对象。

为什么要区分简单数据类型和复杂数据类型

说简单点,相对于java、c++等高级语言一样,就是变量对象的区别,这种区别是可显式的。谈及变量自然离不开内存,今天我们主要以JavaScript为始,以内存的存储方式来展开。


不可变性

在ECMAScript标准中,简单数据类型被定义为primitive values,即原始数值,代表他的值是不可变的。 看到这里,肯定有读者发出疑问:JavaScript里面都是变量啊!不能改变,那不是就成常量了?
别急,我们从内存来逐步理解:
在JavaScript中,变量松散类型的,变量可以保存任何类型的数据。简单来说,每个变量仅仅是一个占位符而已,它里面可以任意存值。

JavaScript中的内存总体分为两种:内存和内存

栈内存

特点:

  • 存储空间的大小固定(即创建时的大小是确定的)
  • 总空间较小
  • 可以直接操作变量,运行效率高(因为JavaScript代码是在栈区执行的)
  • 由编译器分配空间

而JavaScript中的简单数据类型的值,其实就是存储在栈区

先看一下栈区的存储方式
在这里插入图片描述
下面我们通过一道简单的运算题来理解栈内存的存储模式。

	var str="abc";
	str=str+"d"; // "abcd"

上面代码中,我们对str变量进行了:str+“d”,实际上是在栈中又开辟了一块内存空间用来存储新的值“abcd”,然后将str变量指向这块新的内存空间。但是,这并不违背不可变性这一特点
在这里插入图片描述


引用对象

JavaScript中的对象其实就是一堆数据和功能的集合,算是一种数据结构。我们在这里说一下复杂数据类型在内存的存储方式,也就是内存。

堆内存

特点:

  • 存储空间大小不固定,可以动态调整
  • 空间很大
  • 在JavaScript代码中,无法操作其内部存储,要使用地址读取 (运行效率低)
  • 通过代码分配空间

在这里插入图片描述

复杂数据类型就不存在不可变性,我们可以随意改变他们的值:

	obj1.name="李四";
	obj2.age=19;

在这里插入图片描述


Number类型

简称数字类型,可以表示整数和浮点数。在计算机中,数据都是以二进制存储的。当进行计算的时候,数据都是以二进制的形式进行计算,然后将结果转换为十进制打印。 在这个过程中会发生一个很经典的问题:精度丢失,这个问题发生在各种语言中。这是因为存储长度的原因。

JS中对于二进制的存储方式

对于整数来说,除非超过最大范围,否则是不会存在精度问题。主要问题在于小数的存储。因为大多数小数的二进制是无限循环的。

ECMAScript中的Number类型遵循IEEE 754标准。使用64位固定长度来表示。
这其中包括:符合位指数位尾数位

对于JavaScript来说,它使用的是64位双精度浮点数编码,所以它的符号位占1位,指数位占11位,尾数位占52位。

(图片来自网络,侵权删)

  • 符号位:就是表示这个数的正负关系,1表示负,0表示正
  • 指数位:存储科学计数法的指数
  • 尾数位:存储科学计数法的有效数字;

由于尾数位只能存储52位,那么对于53位的数字来说:第53位及以后的数字是不能存储的,它遵循,如果是1就向前一位进1,如果是0就舍弃的原则。这也就是为什么小数计算会产生误差,也就是经典的"0.1+0.2!=0.3"


null 和undefined

ECMAScript规定中,有两个特殊的数据类型,它们有且仅有一个值。

  • null:仅有一个值null,从逻辑上看,null表示一个空对象指针,因为当我们使用typeof操作符时,检测值为null的变量会返回 object。我们可以利用这个值来销毁一些对象的行为。
  • undefined:未定义的。当我们声明一个变量但是未对其赋值,这个变量的值就是undefined。但是有特殊情况,当你直接调用一个未声明的变量时,这个变量时undefined

因为JavaScript是一门动态语言,除了有表示空的null之外,还可能根本就不存在,但是只有在代码运行时才能知道。JavaScript中对于未初始化的变量会自动被赋予undefined


类型检测


typeof

通过typeof操作符,我们很容易能区分出各种简单数据类型。

typeof 123  // number
typeof true  // boolean
typeof '123'  // string
typeof undefined  // undefined

但对于复杂数据类型来说,因为存在特殊的对象,例如DatefunctionArray等等。

typeof [] // object
typeof {} // object
typeof new Array() // object
typeof function(){}  //function

有一个特例,也就是函数(function)。 其他都会被简单判定为object


instanceof

对于上面检测引用类型不准确的情况,instanceof操作符能很好地帮助我们解决问题。

[] instanceof Array // true
new Date() instanceof Date // true
new RegExp() instanceof RegExp // true

instanceof操作符的原理,简单来说就是,左侧是否继承于右侧。在JavaScript中来说,左侧是否在右侧原型链上。


toString

对于引用类型来说,调用toString方法,可以实现引用类型到字符串的转换,并且返回"[object type]"。这里的type,就是这个对象的类型。

 {}.toString() //[object Object]

但是经过我测试后发现,大部分特殊的对象不能实现正确输出。原来,比如ArrayDateRegExp 等都重写了toString()方法,所以我们得不到正确答案。

那么我们怎么才能获得正确结果呢? 其实我们只要调用原始toString()方法就可以了,这时候我们就要借助原始类型上的方法:
Object.prototype.toString().call(arg) arg的值为特殊的对象。


最后

今天的分享就到这里了。虽然总结了不少细节知识,但肯定有我遗漏的知识,希望大家在阅读完毕之后提出宝贵意见!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值