前言
在JavaScript中,数据类型是编程的基础之一,它决定了变量如何存储和操作信息。JavaScript作为一种动态类型语言,其数据类型大致可以分为两大类:原始值(Primitive Values)和对象(Objects)。原始值是最基本的数据单位,包括字符串(String)、数字(Number)、布尔值(Boolean)、null、undefined以及Symbol(ES6引入)和BigInt(ES6引入)。而对象则是一种复合数据类型,可以包含多个键值对(Key-Value Pairs),用于存储和组织复杂的数据结构。
原始值与对象的界限
原始值作为不可变的数据类型,它们本身不支持属性和方法的直接赋值。例如,在尝试为一个数字或字符串直接添加属性时,如示例代码所示,这种操作在技术上是可行的,但实际上并不符合原始值的设计原则。JavaScript引擎(如V8)会在后台进行一些特殊处理,以保持原始值的不可变性。
var num = 123;
num.a = 'aaa'; // 这行代码执行后,num依然是123,不会附加任何属性
上述代码试图为数字num添加一个名为a的属性,但当我们尝试访问这个属性时,会发现它并不存在。这是因为在V8引擎内部,当尝试给原始值赋予属性时,实际上创建了一个临时的对象包装器(如Number对象),然后在这个临时对象上设置属性。一旦该表达式执行完毕,这个临时对象就会被销毁,因此添加的属性也随之消失。
对象的创建方式
JavaScript提供了多种创建对象的方法,每种方法都有其特定的使用场景和优势:
-
对象字面量:这是最直接且常用的方式,通过一对花括号
{}定义一系列键值对来创建对象。var obj = { key: 'value', anotherKey: 'anotherValue' }; -
构造函数:使用
new关键字配合内置构造函数或自定义构造函数来创建对象。内置构造函数如Object、Array、Function等,可以用来创建对应类型的对象。var obj = new Object(); // 创建一个空对象 var arr = new Array(1, 2, 3); // 创建数组对象 -
构造函数模式与原型链:通过自定义构造函数和原型链机制,可以实现对象的复用性和继承。
function Person(name) { this.name = name; } Person.prototype.sayHello = function() { console.log("Hello, I'm " + this.name); }; var person = new Person("Alice"); person.sayHello(); // 输出: Hello, I'm Alice
new操作符的工作原理
new操作符在JavaScript中扮演着至关重要的角色,特别是在面向对象编程中。当使用new调用一个函数时,它会按照以下步骤执行:
- 创建一个新的空对象:首先,
new会创建一个全新的JavaScript对象,即我们常说的实例对象。 - 绑定
this指针:接着,这个新对象会被绑定到构造函数内的this关键字上,使得构造函数内的代码可以给新对象添加属性和方法。 - 执行构造函数:构造函数体内的代码被执行,通常用于初始化新对象的属性。
- 返回新对象:如果构造函数没有显式返回一个非空对象(或者返回的是原始值),则
new操作符会自动返回由第一步创建的新对象。
包装类的奥秘
对于原始值,JavaScript提供了包装类(Wrapper Objects)——String、Number和Boolean,这些类允许原始值短暂地像对象一样操作,拥有属性和方法。然而,这种行为是为了提供便利,并非鼓励直接修改原始值。如前所述,V8引擎在幕后通过valueOf()方法检查包装对象是否代表一个原始值,如果是,则在操作完成后立即丢弃任何附加的属性,确保原始值的不变性。
var str = 'abcd';
console.log(str.length); // 4
在这个例子中,虽然字符串str看起来像是在调用自己的.length属性,但实际上,这是因为字符串包装对象String在后台被创建并调用了.length方法,之后包装对象被销毁,原始字符串值保持不变。
我们再深入一点 分析这段代码的输出值是什么
var str ='abc' // new String('abc')
str +=1 // str = {'abc'} + 1
var test = typeof(str)
if(test.length===6){
test.sign = 'typeOf的返回值结果可能是String'
}
console.log(test.sign);
按上面的分析来理解
var str ='abc' // new String('abc')
str +=1 // str = {'abc'} + 1
var test = typeof(str) // typeof()返回属性'string'
//所以test='string'字符串
if(test.length===6){
test.sign = 'typeOf的返回值结果可能是String'
}
//这里的test.sign代表
//new String('abc').sign = 'new String的结果可能是String'
//接下来v8系统会使用valusOf(test),发现test是原始类,
//就会delete test.sign
console.log(test.sign); // new String(text).sign
所以输出值为undefined
结语
这就是神奇的包装类 希望可以帮助到你,如果觉得有用的话请给奶茶点点赞吧。