js 包装类的作用
前言
在学习 JavaScript 时,我们是否会有一个疑问,在 JS 中不仅引用类型(如 Object、Array 等)有属性和方法,而且连基本类型(如 string、number)也有属性和方法,这是怎么回事呢?
// 例如:
var num = 123;
var str = num.toString(); // 原始值123可以使用toString方法
var name = "vgri";
// 原始值name有length属性,可以使用chartAt方法
console.log(name.length);
console.log(name.charAt(1));
其实啊,JS 为我们提供了三个包装类,通过这三个包装类可以将基本数据类型的数据转换为对象
- String(): 可以基本数据类型字符串转换为 String 对象
- Number(): 可以基本数据类型数字转换为 Number 对象
- Boolean(): 可以基本数据类型布尔值转换为 Boolean 对象
创建基本数据类型的对象
var str = new String("hello"); // str是一个值为'hello'的对象 即:String{'hello'}
var str1 = "hello";
var num = new Number(3); // num是一个值为3的对象 即:String{'hello'}
var num1 = 3;
var bool = new Boolean(true); // bool是一个值为true的对象 即:String{'hello'}
var bool2 = true;
console.log(str); // String {'hello'}
console.log(num); // Number {3}
console.log(bool); // Boolean {true}
console.log(typeof str); // object
console.log(str === str1); // false (str是对象,而str1是字符串)
但是啊,我们在实际应用中不会使用基本数据类型的对象, 如果使用基本数据类型的对象,在做一些比较时可能会带来一些不可预期的结果 那么问题来了,既然实际开发中不用,JS 为什么要提供这三个包装类呢? 在回答这个问题之前,我们先来了解了解为什么基本类型 String、Number、Boolean 也有属性和方法呢? 如字符串的 charAt() 方法 charAt 方法 接收一个参数,基于 0 的字符位置 charAt 方法 是以单字符串的形式返回给定位置的那个字符
var str = "hello world";
console.log(str.charAt(1)); // e
这是为什么呢?好像有点有悖常理,那么现在我们就一探究竟,看看到底是怎么回事? 说回上面,JS 为我们提供了三个包装类,但是实际开发中,我们又不会使用基本类型的对象。
其实,三个包装类的是给后台使用的,比如浏览器,当我们调用比如字符串的方法时,后台会临时通过包装类来创建对象,然后通过对象调用方法,完成之后就会立即销毁,
我们平常写程序的过程:
var str = "sunwukong"; // string 基本类型
var s2 = str.charAt(0);
console.log(s2); // s console.log(str) // sunwukong
实际上在执行 var s2 = str.charAt(0) 这行代码时,后台做了很多工作: JavaScript 高级程序设计里是这样描述的:
- 创建 String 类的一个实例
- 在实例上调用指定的方法
- 销毁这个实例
代码说明如下:
var _str = new String("sunwukong"); // 1.找到对应的包装类,然后通过包装类临时创建一个和基本类型值相同的对象
var s2 = _str.charAt(0); // 2.然后这个对象就可以调用包装对象下的方法,并且返回给 s2
_str = null; // 3.最后自动销毁这个临时创建的对象
所以,此刻我们也就深度理解了为什么基本类型能够调用方法和属性了,原来都是后台在默默的工作,也明白了 JS 中包装类的作用了,就是提供给后台使用的
最后注意一点,
虽然后台会将通过包装类,将基本数据类型转换为实例对象,但是,由于它也会自动销毁该实例,所以我们不能对基本数据类型添加属性和方法,这也符合常理
如:
var dashixiong = "sunwukong";
dashixiong.age = 18;
console.log(dashixiong.age); // undefined
执行到第二行代码属性赋值时,后台通过包装类创建了一个实例,这个 age 属性确实挂到这个临时的实例上去了,但是紧跟着,这个实例就被销毁了,执行到第三行时,又通过包装类重新创建了一个新的实例,这个新实例是没有 age 属性的。