在 JavaScript 的世界里,有一句话广为流传------"万物皆对象"。这不仅仅是一句口号,更是理解 JavaScript 编程的核心。无论是我们常用的数组、函数,还是自定义的数据结构,几乎都可以被视为对象。本文将带你系统梳理 JS 对象的基础知识,帮助你打下坚实的 JavaScript 编程基础。
一、什么是对象?
对象(Object)是 JavaScript 中最重要的数据类型之一。它是一组无序的相关属性和方法的集合。每个属性由键(key)和值(value)组成,值可以是任意类型的数据,包括基本类型、对象、函数等。
举个例子:
js
let person = {
name: "张三",
age: 25,
sayHello: function() {
console.log("你好,我是" + this.name);
}
};
在上面的代码中,person
就是一个对象,包含了 name
、age
两个属性和一个 sayHello
方法。
二、创建对象的三种方式
JavaScript 提供了多种创建对象的方法,常见的有三种:
1. 字面量方式
这是最常用、最简洁的方式。直接用大括号包裹属性和方法即可。
js
let obj = {
key1: "value1",
key2: "value2"
};
2. 使用 new Object()
通过 new
关键字和 Object
构造函数创建对象,然后再为对象添加属性。
js
let obj = new Object();
obj.key1 = "value1";
obj.key2 = "value2";
3. 使用自定义构造函数
当我们需要批量创建结构相似的对象时,可以自定义构造函数。
js
function Person(name, age) {
this.name = name;
this.age = age;
this.sayHello = function() {
console.log("你好,我是" + this.name);
};
}
let p1 = new Person("李四", 30);
let p2 = new Person("王五", 28);
通过构造函数,可以方便地创建多个拥有相同属性和方法的对象实例。
三、构造函数与 new
关键字
构造函数本质上就是一个普通的函数,但约定俗成地首字母大写。当函数被 new
关键字调用时,会发生以下三件事:
- 创建一个新的 this 对象。
- 执行构造函数中的代码,将属性和方法添加到 this 对象上。
- 返回 this 对象。
这就是为什么我们可以通过 new
关键字批量创建对象实例的原因。
四、包装类与自动拆箱
在 JavaScript 中,原始类型(如 number、string、boolean)在需要时会被自动包装成对象,这些包装类分别是 Number
、String
、Boolean
。例如:
js
let num = 123;
let objNum = new Number(num);
当我们对字面量调用方法时,JS 会自动将其包装成对象:
js
let str = "hello";
console.log(str.length); // 实际上是 new String(str).length
但需要注意的是,包装对象的属性在参与运算时会被自动拆箱成原始类型,且 JS 是弱类型语言,只有在赋值时才会判断类型。如果一个包装对象被判定为原始类型,其上添加的属性会被移除。
js
let n = new Number(10);
n.myProp = "test";
console.log(n.myProp); // "test"
let m = n + 1; // 自动拆箱为 10
console.log(m.myProp); // undefined
五、判断数据类型
在实际开发中,我们经常需要判断变量的数据类型。typeof
操作符可以准确判断除 null
以外的所有原始类型:
js
console.log(typeof 123); // "number"
console.log(typeof "abc"); // "string"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object"(这是 JS 的一个历史遗留问题)
console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(typeof function(){}); // "function"
需要注意的是,typeof null
返回的是 "object"
,这是 JavaScript 早期设计的一个 bug,但一直被保留了下来。
六、案例解析:原始类型与对象的本质区别
在 JavaScript 中,原始类型(如 number、string、boolean)和对象有着本质的区别。通过实际代码案例,我们可以更直观地理解两者的不同。
1. 原始类型不能添加属性和方法
js
var num = 123; // 实际上是原始类型 number
num.a = 'aaa';
delete num.a;
console.log(num.a); // 输出 undefined
在上面的代码中,我们尝试给一个 number 类型的变量 num
添加属性 a
,但实际上并没有生效。原因在于,原始类型的数据在赋值时不会变成对象,属性的添加和删除操作都不会被保留。
2. 包装类对象可以添加属性
js
var num = new Number(123);
num.a = 'aaa';
console.log(num + 1); // 输出 124
console.log(num.a); // 输出 'aaa'
当我们用 new Number(123)
创建一个包装对象时,这个对象就可以像普通对象一样添加属性和方法。此时,num
是一个对象,而不是原始类型。
3. 字符串的 length 属性
js
var str = 'hello'; // 实际上是原始类型 string
console.log(str.length); // 输出 5
虽然 str
是原始类型,但我们依然可以访问 length
属性。这是因为在访问属性时,JavaScript 会临时将原始类型包装成对应的对象(如 String
),访问完毕后立即销毁这个临时对象。
4. 数组和字符串的 length 属性操作
js
var arr = [1, 2, 3, 4, 5];
arr.length = 2;
console.log(arr); // 输出 [1, 2]
数组的 length
属性是可写的。当我们将 arr.length
设为 2 时,数组会被截断,只保留前两个元素。
js
var str = 'abcd';
str.length = 2;
console.log(str); // 输出 'abcd'
而字符串的 length
属性是只读的,尝试修改不会生效,字符串本身也不会被截断。这再次说明了原始类型和对象的不同。 这一行看似是给字符串的 length
属性赋值,但实际上不会生效,原因如下:
- 在 JavaScript 中,字符串是原始类型,原始类型本身不能添加或修改属性。
- 当你访问
str.length
时,JavaScript 会临时把str
包装成一个String
对象,让你可以读取length
属性(此时值为 4)。
- 但是,当你尝试给
str.length
赋值时,JavaScript 依然会临时包装成对象,但这个赋值只会作用在这个临时对象上,不会影响原始字符串本身,而且这个临时对象会立刻被销毁。
- 所以,
str.length = 2
; 这行代码什么实际效果都没有,字符串的长度不会被改变,str
依然是'abcd'
。
5、知识点总结与面试考点
- 原始类型不能添加自定义属性和方法,即使语法上允许写,但不会被保留。
- 包装类对象可以添加属性和方法,但在参与运算时会自动拆箱为原始类型。
- 字符串的 length 属性是只读的,不能通过赋值改变字符串的长度。
- 数组的 length 属性是可写的,可以通过赋值来截断或扩展数组。
- 原始类型在访问属性时会被临时包装成对象,访问结束后临时对象被销毁,添加的属性不会保留。
七、总结
JavaScript 对象是 JS 编程的基石。掌握对象的创建方式、构造函数的原理、包装类的自动拆箱机制,以及数据类型的判断方法,是每一个 JS 开发者的必修课。希望本文能帮助你理清 JS 对象的核心知识点,为后续深入学习打下坚实基础。
如果你觉得这篇文章对你有帮助,欢迎点赞、收藏和分享!