变量和类型
1.JavaScript规定了几种语言类型
两种类型:基本类型和引用类型
注:JavaScript无法直接操作对象的内存空间
基本类型
-
基本类型有:Boolean、String、Number、Null、Undefined、Symbol、BigInt
-
访问:基本数据类型 按值访问
-
存储:存放在栈内存中
引用类型
-
引用类型有:Object、Array、Function、RegExp、Date
-
访问:基本数据类型 按引用访问
-
存储:引用类型的值是存放在堆内存中的对象Object;在栈内存中包含了指向堆内存中该对象的指针,堆内存中包含了对象内容
2.JavaScript装箱拆箱(基本类型)
- 装箱:把基本类型转换为对应的引用类型
隐式装箱:
1.读取基本类型的值,后台创建临时的对应该基本类型的对象
(创建一个实例)
2.对基本类型调用的方法,本质是在该基本类型对应的对象上的方法
(调用实例的方法)
3.执行方法后,后台立马销毁。 xxx = null
(销毁实例)
//隐式装箱
var a = 'liuXing'
a.indexOf('X')
//他在后台的真正操作是
var a = new String('liuXing')
a.indexOf('X')
a = null
显式装箱
直接用内置对象Number、Boolean、String、Object等 对基本类型进行显式装箱
//显式装箱
var a = new String('liuXing')
拆箱:把引用类型转换为对应的基本类型
内部过程:调用了一个抽象方法toPrimitive(val, type),type参数为非必传,type的意义是对象被期待转换的类型。
1.如果val是object,则先执行valueOf()方法,如果结果为原始值,则返回此结果;
2.调用tostring()方法;如果得出结果为原始值,则返回结果,否则抛出异常;
//拆箱就是把引用类型转化为基本类型的数据,通常通过引用类型的valueof()和toString()方法实现
let name = new String('liuXing')
let age = new Number(23)
console.log(typeof name) // object
console.log(typeof age) // object
// 拆箱操作
console.log(typeof age.valueOf()); // number // 23 基本的数字类型
console.log(typeof name.valueOf()); // string // 'liuXing' 基本的字符类型
console.log(typeof age.toString()); // string // '23' 基本的字符类型
console.log(typeof name.toString()); // string // 'liuXing' 基本的字符类型
3.null 和 undefined
在JavaScript中,null和undefined几乎相等,但是:
console.log(null==undefined); //true 两者默认转换成了false
console.log(typeof undefined); //"undefined"
console.log(typeof null); //"object"
console.log(null===undefined); //false
区别:
- Bug——typeof null 为object的原因:对象在底层都表示为二进制,在 JavaScript 中二进制前三位都为 0 的话会被判断为 object 类型, 但是null 的二进制表示是全都是 0,所以执行 typeof 时会返回“ object ”。
- 转换为number数据类型时,null 默认转换成0,undefined默认转换为 NaN
- null是原型链的终点,表示没有对象;undefined表示此处应该有值,但是没有被定义,有可能是定义了行参却没传实参,或者属性不存在、函数没有返回值、return未赋值等情况。
4.JavaScript的精度丢失问题
JavaScript作为解释性语言,直接计算会有浮点数精度丢失问题。原因是JavaScript的浮点数实现也是遵循IEEE 754标准,采用双精度存储(double precision),进行了相关的实现。但是到了计算机的最底层,是通过1和0的机器码来对具体的数据和操作进行具体的实现。由于底层实现机制的原因,浮点数在转换为二进制表示的时候,无法精确表示这种包含小数点的数据,其本质是将浮点数转换成了用二进制表示的最接近的近似值。因此采用**“四舍五入法”(逢1进,逢0舍)**。以上就是问题产生的原理,很多编译型语言如Java,c#等都对浮点数的处理进行了封装。因此平时大多数情况下并不会出现明显的可见的问题。js本身作为解释性语言,好像这点上有着天生的劣势。网络上解决方式,也大多数是通过自定义的方法去解决这个问题,原理基本都大同小异。
- 本质上在处理这类问题的时候,基本的思路就是通过将浮点数转换成整数进行计算,然后再将整数的小数点位调整,转回正确的浮点数结果。
- 通过引入 math.js 或者 bigNumber.js 进行解决
- BigInts 是 JavaScript 中的一个新的数字基本(primitive)类型,可以用任意精度表示整数。使用 BigInt 可以安全地存储和操作大整数,即使这个数已经超出了 Number 能够表示的安全整数范围。本文将介绍一些用例,并通过比较 JavaScript 中的 BigInts 和 Number 来解释 Chrome 67 中的新功能。
- 使用BigInt或者选择使用JSBI库。BigInt是一种新的数据类型,用于当整数值大于Number数据类型支持的范围时。这种数据类型允许我们安全地对大整数执行算术操作,表示高分辨率的时间戳,使用大整数id,等等,而不需要使用库。
重要的是要记住,不能使用Number和BigInt操作数的混合执行算术运算,需要通过显式转换其中的一种类型。 此外,出于兼容性原因,不允许在BigInt上使用一元加号(+)运算符。
5.JavaScript的隐式转换
链接: 隐式转换.
6.手写实现一个Symbol
链接: 手写Symbol.