包装类型
为了更好操作原始类型数据,js还引入了三种特殊的引用类型Number、String、Boolean,我们称其为包装类型
什么是包装类型
使用new操作符创建一个原始类型实例的方式我们叫做创建一个包装类型
下面我们使用一个例子来说明:
console.log(122799 === new Number(122799)) // false
console.log("LDec.27" === new String("LDec.27")) // false
console.log(true === new Boolean(true)) // false
// === 是严格相等,其左右两边的值和类型都相等才会返回true
console.log(typeof new Number(122799)); // object
console.log(typeof new String("LDec.27")); // object
console.log(typeof new Boolean(true)); // object
我们可以发现相同值的原始类型与其包装类型使用严格相等运算符判断是不相等的,经过类型判断后我们发现包装类型的类型是object
为什么要引入包装类型
原始类型的数据是不可变的,但是如String类型中有许多方法,而只有对象才能拥有方法,才可以添加属性,所以我们要使用包装类型来对原始类型数据进行操作,因为包装类型是对象,对象我们可以调用其方法和添加属性
下面引入一个例子
let p1 = "LDec.27"
p1.hobby = "basketball"
console.log("p1",p1.hobby) // undefined
let p2 = new String("LDec.27")
p2.hobby = "basketball"
console.log("p2",p2.hobby) // basketball
我们发现正常定义一个原始类型变量我们在其身上添加属性最后输出结果是undefined,而我们创建一个String的包装类型并在其身上添加相同的属性最后是可以输出结果的
"1".toString()这段代码是怎么运行的
按照我们上面的说法"1"是原始类型的数据,我们本应无法调用方法和添加属性的但是我们输出结果时偏偏成功了这是为什么呢?
其实在代码执行阶段就会默默帮我们创建对应类型的包装类型
代码在执行阶段默默帮我们做了这三件事
- 创建一个String包装类型 s = new String("1")
- 调用toString()方法 s.toString()
- 销毁这个包装类型 s = null
所以我们可以自己主动创建包装类型,也可以在操作原始类型时自动帮我们创建原始类型
包装类型与引用类型的区别在哪里
包装类型和引用类型使用typeof操作符判断其类型都会返回object,那么都是对象它们直接的区别在哪里呢
其实它们的区别在于生命周期的长短
-
引用类型
引用类型在代码执行完其所在作用域代码之前会一直存在于内存中
-
包装类型
包装类型在执行完其所在一行代码时就会被销毁,如:"1".toString()
推荐使用new Object()创建包装类型
因为Symbol和BigInt类型无法使用new操作符创建实例对象
let symbol = new Symbol("111") // TypeError: Symbol is not a constructor
let bigInt = new BigInt("111") // TypeError: BigInt is not a constructor
使用Object构造函数创建实例对象就像工厂模式一样,我们传入原始类型的数据就会为我们创建对应其类型的包装类型
let p3 = new Object("LDec.27")
p3.hobby = "basketball"
console.log("p3",p3.hobby) // basketball
包装类型不能与转型函数搞混
我们不能直接使用转型函数来创建包装类型
包装类型与转型函数是不同的,包装类型的类型是object,转型函数的类型是其所代表的原始类型
let value = "12345"
let num = Number(value)
console.log(typeof num) // number
let num2 = new Number(value)
console.log(typeof num2) // object