JavaScript对象指南:从基础概念到内置方法详解
什么是JavaScript对象?
在JavaScript中,对象是一种复合数据类型,可以容纳多个值。可以把对象想象成一个容器,里面存放着相关的数据和功能。对象是JavaScript中最基础的数据类型之一,几乎everything in JavaScript is an object或可以表现为对象。
生活类比:
想象一辆汽车。汽车有颜色、品牌、型号、价格等属性,还能启动、加速、刹车。在这类比中:
-
汽车本身就是一个对象
-
颜色、品牌、型号是对象的属性(Properties)
-
启动、加速、刹车是对象的方法(Methods)
// 汽车对象的JavaScript表示
let car = {
brand: '丰田',
model: '凯美瑞',
color: '黑色',
price: 240000,
// 方法
start: function() {
console.log('汽车启动');
},
accelerate: function() {
console.log('汽车加速');
}
};
对象的语法结构
对象字面量语法
const objectName = {
key1: value1,
key2: value2,
key3: value3
};
语法说明:
-
使用花括号
{}定义对象的开始和结束 -
内部包含多个键值对,用逗号分隔
-
每个键后面跟冒号
:,然后是值 -
值可以是任何数据类型:字符串、数字、布尔值、数组、函数、甚至他对象
创建对象的多种方式
1. 对象字面量(最常用)
// 最简单的对象创建方式
let student = {
name: '张三',
age: 20,
major: '计算机科学',
scores: [85, 92, 78],
introduce: function() {
console.log(`我叫${this.name},今年${this.age}岁`);
}
};
student.introduce(); // 我叫张三,今年20岁
个人经验:对象字面量是我日常开发中使用最多的方式,简洁直观,适合创建单一对象实例。
2. 使用new关键字
// 创建空对象再添加属性
let person = new Object();
person.name = '李四';
person.age = 25;
person.job = '工程师';
person.sayHi = function() {
console.log('你好,我是' + this.name);
};
person.sayHi(); // 你好,我是李四
3. 构造函数模式
// 定义构造函数
function Student(name, age, major) {
this.name = name;
this.age = age;
this.major = major;
this.introduce = function() {
console.log(`${this.name},${this.age}岁,专业:${this.major}`);
};
}
// 创建多个实例
let student1 = new Student('王五', 22, '软件工程');
let student2 = new Student('赵六', 21, '数据科学');
student1.introduce(); // 王五,22岁,专业:软件工程
student2.introduce(); // 赵六,21岁,专业:数据科学
个人见解:构造函数适合需要创建多个相似对象的场景,比重复写对象字面量更高效。
4. Object.create()方法
// 原型对象
let animal = {
type: '动物',
speak: function() {
console.log(this.name + '发出声音');
}
};
// 基于原型创建新对象
let dog = Object.create(animal);
dog.name = '旺财';
dog.breed = '金毛';
dog.speak(); // 旺财发出声音
let cat = Object.create(animal);
cat.name = '';
cat.speak(); // 发出声音
JavaScript对象的可变性
对象与原始类型较大的区别在于:对象是可变的(Mutable)。
let user = {
username: 'alex',
age: 28,
email: 'alex@example.com'
};
console.log('原始对象:', user);
// 修改现有属性
user.age = 29;
console.log('修改后:', user); // age变为29
// 添加新属性
user.phone = '13800138000';
console.log('添加后:', user); // 新增phone属性
// 删除属性
delete user.email;
console.log('删除后:', user); // email属性被移除
// 对象本身不变,但内容变了
console.log('对象引用不变,内容已变');
为什么可变性很重要?
当对象被传递给函数时,传递的是引用,函数内部修改会影响原对象:
function updateAge(person) {
person.age += 1; // 直接修改原对象
console.log('函数内部:', person.age);
}
let user2 = { name: '张三', age: 25 };
console.log('调用前:', user2.age); // 25
updateAge(user2); // 函数内部:26
console.log('调用后:', user2.age); // 26(原对象被修改)
对象的属性操作
访问属性
let book = {
title: 'JavaScript高级程序设计',
author: 'Nicholas',
'publication-year': 2024,
price: 99
};
// 点号语法(常用)
console.log(book.title); // JavaScript高级程序设计
console.log(book.author); // Nicholas
// 方括号语法(处理特殊属性名)
console.log(book['publication-year']); // 2024
// 变量作为属性名
let prop = 'price';
console.log(book[prop]); // 99
遍历对象属性
let product = {
name: '笔记本电脑',
brand: '联想',
price: 5999,
inStock: true
};
// 使用for...in循环
for (let key in product) {
console.log(`${key}: ${product[key]}`);
}
// 输出:
// name: 笔记本电脑
// brand: 联想
// price: 5999
// inStock: true
// 使用Object.keys()获取所有键
console.log(Object.keys(product)); // ['name', 'brand', 'price', 'inStock']
// 使用Object.values()获取所有值
console.log(Object.values(product)); // ['笔记本电脑', '联想', 5999, true]
// 使用Object.entries()获取键值对数组
console.log(Object.entries(product));
// [['name', '笔记本电脑'], ['brand', '联想'], ['price', 5999], ['inStock', true]]
常用的内置对象方法
1. Object.create() - 基于原型创建对象
const personPrototype = {
greet: function() {
console.log(`你好,我是${this.name}`);
},
is: function() {
return this.age >= 18;
}
};
let employee = Object.create(personPrototype, {
name: { value: '李华', writable: true },
age: { value: 28, writable: true },
job: { value: '工程师', writable: true },
salary: { value: 15000, writable: true }
});
employee.greet(); // 你好,我是李华
console.log(employee.is()); // true
console.log(employee.job); // 工程师
2. Object.entries() - 获取键值对数组
const user = {
id: 1001,
username: 'alex123',
email: 'alex@example.com',
active: true
};
const entries = Object.entries(user);
console.log(entries);
// [['id', 1001], ['username', 'alex123'], ['email', 'alex@example.com'], ['active', true]]
// 实用场景:将对象转换为URL参数
function objectToQueryString(obj) {
return Object.entries(obj)
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
.join('&');
}
console.log(objectToQueryString(user));
// id=1001&username=alex123&email=alex%40example.com&active=true
3. Object.keys() - 获取所有属性名
const settings = {
theme: 'dark',
fontSize: 14,
showNotifications: true,
language: 'zh-CN'
};
console.log(Object.keys(settings)); // ['theme', 'fontSize', 'showNotifications', 'language']
// 实用场景:检查对象是否为空
function isEmpty(obj) {
return Object.keys(obj).length === 0;
}
console.log(isEmpty({})); // true
console.log(isEmpty({a: 1})); // false
4. Object.values() - 获取所有属性值
const scores = {
math: 95,
english: 88,
physics: 92,
chemistry: 85
};
const values = Object.values(scores);
console.log(values); // [95, 88, 92, 85]
// 计算平均分
const average = values.reduce((sum, score) => sum + score, 0) / values.length;
console.log('平均分:', average.toFixed(2)); // 平均分:90.00
5. Object.is() - 严格相等比较
console.log(Object.is(25, 25)); // true
console.log(Object.is('hello', 'hello')); // true
console.log(Object.is(true, false)); // false
// 特殊情况的处理
console.log(Object.is(0, -0)); // false(区分正负零)
console.log(0 === -0); // true(三等号不区分)
console.log(Object.is(NaN, NaN)); // true
console.log(NaN === NaN); // false(三等号认为NaN不等于自身)
6. Object.assign() - 对象合并与复制
// 合并多个对象
const defaults = {
theme: 'light',
fontSize: 12,
showSidebar: true
};
const userConfig = {
fontSize: 16,
language: 'en'
};
const finalConfig = Object.assign({}, defaults, userConfig);
console.log(finalConfig);
// {theme: 'light', fontSize: 16, showSidebar: true, language: 'en'}
// 浅拷贝对象
const original = { a: 1, b: { c: 2 } };
const copy = Object.assign({}, original);
console.log(copy); // {a: 1, b: {c: 2}}
console.log(copy === original); // false(不同对象)
// 注意:Object.assign是浅拷贝
copy.b.c = 100;
console.log(original.b.c); // 100(原对象也被修改)
7. Object.freeze() - 冻结对象
const CONFIG = {
apiUrl: 'https://api.example.com',
version: '1.0.0',
maxRetries: 3
};
Object.freeze(CONFIG);
// 尝试修改(严格模式下会报错,非严格模式静默失败)
CONFIG.version = '2.0.0'; // 无效
CONFIG.newProperty = 'test'; // 无效
delete CONFIG.maxRetries; // 无效
console.log(CONFIG); // 原对象不变
// 检查对象是否冻结
console.log(Object.isFrozen(CONFIG)); // true
8. Object.seal() - 密封对象
const userProfile = {
name: '张三',
age: 30,
email: 'zhangsan@example.com'
};
Object.seal(userProfile);
// 可以修改现有属性
userProfile.age = 31;
console.log(userProfile.age); // 31
// 不能添加新属性
userProfile.phone = '123456789'; // 无效
console.log(userProfile.phone); // undefined
// 不能删除属性
delete userProfile.email; // 无效
console.log(userProfile.email); // zhangsan@example.com
// 检查对象是否密封
console.log(Object.isSealed(userProfile)); // true
对象属性的高级特性
属性描述符
let person = {
name: '李华'
};
// 获取属性描述符
let descriptor = Object.getOwnPropertyDescriptor(person, 'name');
console.log(descriptor);
// {value: '李华', writable: true, enumerable: true, configurable: true}
// 定义具有特定属性的属性
Object.defineProperty(person, 'age', {
value: 25,
writable: false, // 不可修改
enumerable: true, // 可枚举
configurable: false // 不可配置(不能删除,不能修改描述符)
});
person.age = 30; // 无效(因为writable为false)
console.log(person.age); // 25
delete person.age; // 无效(因为configurable为false)
console.log(person.age); // 25
课程知识要点
-
对象定义:JavaScript对象是键值对的,可以包含各种数据类型
-
创建方式:对象字面量、new Object()、构造函数、Object.create()
-
可变特性:对象是引用类型,内容可以修改,传递的是引用
-
属性操作:点号语法、方括号语法、添加、修改、删除属性
-
遍历方法:for...in、Object.keys()、Object.values()、Object.entries()
-
对象比较:Object.is()提供严格的相等比较,区分NaN和±0
-
对象合并:Object.assign()用于浅拷贝和合并对象
-
对象控制:Object.freeze()冻结、Object.seal()密封、Object.defineProperty()精细控制
-
原型继承:Object.create()基于原型创建对象
开发实践建议
基于多年JavaScript开发经验,我对对象使用的建议如下:
推荐做法:
-
创建单个对象优先使用对象字面量
{} -
需要多个同类对象使用构造函数或class
-
使用Object.freeze()保护配置对象
-
使用解构赋值获取对象属性
-
使用可选链操作符
.安全访问嵌套属性
// 现在JavaScript对象操作示例
class User {
constructor(data) {
this.id = data.id;
this.name = data.name;
this.email = data.email;
this.createdAt = data.createdAt || new Date();
}
get info() {
return `${this.name} (${this.email})`;
}
update(data) {
Object.assign(this, data);
}
}
// 使用示例
const userData = {
id: 1001,
name: '王小明',
email: 'wang@example.com'
};
const user = new User(userData);
console.log(user.info); // 王小明 (wang@example.com)
user.update({ name: '王晓明' });
console.log(user.name); // 王晓明
// 安全访问嵌套属性
const response = {
data: {
user: {
profile: {
displayName: '小明同学'
}
}
}
};
// 传统方式(报错)
// const name = response.data.user.profile.displayName;
// 现在安全方式
const displayName = response.data.user.profile.displayName '匿名';
console.log(displayName); // 小明同学
对象是JavaScript的核心,深入理解对象及方法,是写出高质量代码的基础。掌握这些知识,你就能更好地组织数据、构建复杂的应用逻辑。