本文深入解析JavaScript中字符串、数字和布尔值的包装对象机制。说明原始值在调用属性或方法时如何隐式转换为临时对象,以及该对象的销毁过程。通过对比显式包装与隐式包装,阐述字符串不可变性对属性赋值的影响,并详细区分==与===运算符在原始值与包装对象间的比较差异。
JavaScript 字符串对象基础
JavaScript 对象是一种复合值,由一组属性或命名值构成,通常通过点运算符(.)来访问属性。当属性值为函数时,该属性被称为方法。本文将重点讲解 JavaScript 中的 String 对象及其相关特性。
在编写 JavaScript 代码时,经常需要调用字符串的 length 属性,以及 substring()、charAt()、indexOf() 等方法。需要特别注意的是,JavaScript 中的字符串对象是不可变的。虽然可以使用 + 运算符拼接字符串来创建新的字符串对象,但在处理大量字符串拼接时,建议使用 [].join() 方式以提高性能。
具体示例如下:
var str="javascript";
var len=str.length;
var substr=str.substring(2,len);
隐式包装与字符串不可变性
这里存在一个常见疑问:字符串作为原始数据类型,为何拥有属性?在 JavaScript 中,使用双引号或单引号包裹的内容被称为字符串字面量。当对字符串调用 length 属性或其方法时,JavaScript 引擎会隐式地通过 new String(str) 构造函数将字符串值转换为一个对象。这个临时对象继承了字符串的方法,并用于处理属性的引用。一旦引用操作结束,该临时对象会被自动销毁。类似地,数字和布尔类型也拥有各自的方法,它们通过 new Number() 和 new Boolean() 构造函数创建临时对象来支持方法调用。而 null 和 undefined 没有对应的包装对象,尝试访问它们的属性会抛出类型错误。
以下代码模拟了这一过程:
var str = "test";
str.length = 10;
str.testStrLen = 10;
var res = str.length;
console.log(res);//输出4
res = str.testStrLen;
console.log(res);//输出undefined
当执行上述代码时,res 的值输出为 4 和 undefined。第二行代码尝试覆盖字符串原本的 length 属性,第三行尝试增加一个 testStrLen 属性。最终输出结果并未达到预期,原因在于第二行和第三行代码分别创建了一个临时的字符串对象,随后该临时对象立即被销毁。当再次读取 length 时,获取的是原始字符串中的 length 属性;而尝试读取 testStrLen 时,引擎沿原型链查找但未找到,因此返回 undefined。这段测试代码表明,读取字符串时表现得像对象调用,但如果试图给其属性赋值,操作会被忽略,因为修改仅发生在已销毁的临时对象上。
显式包装与属性赋值行为
存取字符串、数字、布尔类型值的属性时创建的临时对象被称为包装对象,它用于区分字符串值与字符串对象、数字值与数值对象、布尔值与布尔对象。包装对象仅被视为一种实现细节,通常无需特别关注。由于字符串、数字和布尔值的属性都是只读的,且不能为原始值定义新属性,这有助于理解它们与包装对象之间的区别。
需要注意的是,可以通过 String()、Number()、Boolean() 构造函数显式地创建包装对象。
var str = new String("test");
str.length = 10;
str.testStrLen = 10;
var res = str.length;
console.log(res);//输出4
res = str.testStrLen;
console.log(res); //输出10
通过上述代码,我们成功给 str 这个字符串对象增加了 testStrLen 属性,但并未成功覆盖原来的 length 属性。由此可以推断,在原型链读取时,自身属性优先级高于原型链属性,找到即停止查找。testStrLen 的成功追加也印证了通过字符串直接追加属性时,会创建一个临时的字符串对象。
包装对象与原始值的比较
接下来比较包装值与未包装值的相等性。
var str1 = new String("test");
var str2 = "test";
console.log(str1 == str2);//true
console.log(str1 === str2);//false
var n1 = new Number(1);
var n2 = 1;
console.log(n1 == n2);//true
console.log(n1 === n2);//false
var b1 = new Boolean(false);
var b2 = false;
console.log(b1 == b2);//true
console.log(b1===b2);//false
由此可见,JavaScript 会在必要时将包装对象转换为原始值。== 运算符将原始值与其包装对象视为相等,但 === 全等运算符将它们视为不等。通过 typeof 运算符可以观察到原始值与其包装对象类型的不同。例如:
var str1 = new String("test");
var str2 = "test";
console.log(str1 == str2);//true
console.log(str1 === str2);//false
console.log(typeof str1); //object
console.log(typeof str2); //string
var n1 = new Number(1);
var n2 = 1;
console.log(n1 == n2);//true
console.log(n1 === n2);//false
console.log(typeof n1); //object
console.log(typeof n2); //number
var b1 = new Boolean(false);
var b2 = false;
console.log(b1 == b2);//true
console.log(b1 === b2);//false
console.log(typeof b1); //object
console.log(typeof b2); //boolean
常见的 typeof 返回类型

js数据类型 参考
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/typeof
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Data_structures
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。