前言
错误理解:
之前对Js基本包装类型的理解是,当我们创建了一个基本类型的变量时,Js会自动为我们将其包装(转换)成基本包装类型的实例,所以我们才能直接调用它的属性的方法。
let str = 'hello'
substr = str.substring(2)
其实关于str到底是什么类型,我也没有太在意过,今天偶尔的一个测试却让我发现事情没有那么简单。
可以看到,str不是一个实例对象,而是一个基本类型变量
var str = "string"
console.log(str instanceof String)
console.log(typeof str)
所以这也就触发了我今天对基本包装类型的探究,总结如下:
基本包装类型
为了便于操作基本类型值,ECMAScript提供了一些特殊的引用类型:比如Boolean、Number和String等。这些类型与其他引用类型相似,但具有与各自的基本类型相应的特殊行为。
除了 null 和 undefined 之外,所有基本类型都有其对应的包装对象:
String Number BigInt Boolean Symbol
按道理基本数据类型是没有属性和方法的,对象才有属性和方法。
但下面代码却可以执行:
let str = 'hello';
substr = str.substring(2);
原理
实际上,每当我们对一个保存了基本类型值(比如number,string和boolean)的变量调用方法(或者访问属性)的时候,后台就会创建一个对应的基本包装类型的对象,对他们调用我们所指定的方法来得到我们想要的数据。
具体过程如下:
-
根据对象保存的基本类型值,创建对应类型的实例对象 -
在这个实例上调用我们所指定的方法 -
立即销毁这个实例
上边声明了str变量,并对其调用substring方法的代码等同于下边代码:
let str = 'hello';
var temp = new String(str);
substr = temp.substring();
temp = null;
引用类型与基本包装类型的主要区别就是对象的生存期,使用new创建的引用类型实例当执行流离开当前作用域之前,都一直保存在内存中,而自动创建的基本包装类型的对象,则只存在于一行代码执行的瞬间,然后就被销毁。这就意味着我们不能给基本包装类型添加属性和方法。
let s = 'JavaScript';
s.language = 'ECMAScript';
console.log(s.language);
上边代码试图给s添加一个language属性,但是当我们再次输出该属性的时候却得到undefined。
这是因为s.language = 'ECMAScript'; 这句代码执行时,Js内部创建了一个String类型的实例,并在这个实例身上添加了language属性,但是这行代码执行完毕之后,这个实例马上就被销毁了,当我们执行console.log(s.language); 这句代码时,又重新创建了一个实例对象,这个实例对象和上一句代码所创建的实例对象不是一个,自然也没有language属性。
一般来说,不推荐直接声明基本包装类型对象。
let n = new Number(10);
let s = new String('JS');
let b = new Boolean(false);
我们只需要知道基本包装类型对象身上(准确的来说是他的原型身上)有哪些方法,我们直接声明基本类型变量调用即可。
总结
- 基本包装类型的实例会在我们调用一些基本类型变量方法(或属性)的时候被自动创建
- 我们对基本类型变量调用的方法(或访问属性),Js底层会对基本包装类型实例操作
- 基本包装类型的实例只会存在于一行代码执行的一瞬间,然后就会被立即销毁
- 不推荐手动创建基本包装类型实例
|