【前端教程】JavaScript 对象与数组操作实战:从基础到优化
·
在JavaScript编程中,对象和数组是构建复杂应用的基础。本文将通过多个实用案例,从原始实现出发,逐步优化代码,带你掌握对象创建、数组操作、数据遍历等核心技能。每个案例都包含原始代码解析、优化方案及关键知识点说明,帮助你写出更规范、高效的JavaScript代码。
案例1:创建人类对象及方法实现
需求说明
创建一个包含编号、名称、年龄、性别属性的人类对象,添加"吃饭"功能,并在页面展示该对象信息。
原始代码实现
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>人类对象示例</title>
<script>
var person={
'bianhao':007,
'name':'诗书画唱',
'age':20,
'sex':'男',
'chifan' :function(){
alert(this.name+"正在吃饭");
}
};
for(var i in person){
document.write(person[i]+" ");
}
document.write("<hr>");
document.write(person.bianhao+" "+person.name + " "+person.age+" "+person.sex);
person.chifan();
</script>
</head>
<body>
</body>
</html>
原始代码解析
- 使用对象字面量创建了
person对象,包含属性和方法 - 通过
for...in循环遍历对象属性并输出 - 直接通过点语法访问属性并输出
- 调用
chifan方法弹出提示框
存在的问题
- 使用
var声明变量,缺乏块级作用域 - 编号
007作为数字会被解析为7,丢失前导零 - 使用
document.write()输出内容,不利于页面布局控制 - 弹窗提示用户体验不佳
- 代码结构混乱,展示逻辑与数据混合
优化方案
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>优化后的人类对象示例</title>
<style>
.person-card {
border: 1px solid #ccc;
padding: 15px;
max-width: 300px;
margin: 20px;
border-radius: 5px;
box-shadow: 0 2px 3px rgba(0,0,0,0.1);
}
.person-info {
margin: 8px 0;
}
.action-btn {
margin-top: 10px;
padding: 6px 12px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.action-btn:hover {
background-color: #45a049;
}
.status {
margin-top: 10px;
color: #666;
font-style: italic;
}
</style>
</head>
<body>
<div class="person-card" id="personCard"></div>
<script>
// 使用const声明常量对象,属性使用更规范的命名
const person = {
id: '007', // 改为字符串保留前导零
name: '诗书画唱',
age: 20,
gender: '男', // 使用更规范的属性名
// 吃饭方法,改为更新页面状态而非弹窗
eat: function() {
const statusElement = document.getElementById('status');
statusElement.textContent = `${this.name}正在吃饭`;
}
};
// 渲染人员信息到页面
function renderPersonInfo(person) {
const card = document.getElementById('personCard');
// 创建信息展示区域
card.innerHTML = `
<h3>人员信息</h3>
<div class="person-info"><strong>编号:</strong>${person.id}</div>
<div class="person-info"><strong>姓名:</strong>${person.name}</div>
<div class="person-info"><strong>年龄:</strong>${person.age}</div>
<div class="person-info"><strong>性别:</strong>${person.gender}</div>
<button class="action-btn" onclick="person.eat()">执行吃饭动作</button>
<div class="status" id="status"></div>
`;
}
// 页面加载完成后渲染信息
window.onload = function() {
renderPersonInfo(person);
};
</script>
</body>
</html>
优化点说明
- 变量声明:使用
const替代var,明确变量不可变 - 属性命名:使用更规范的英文命名(如
id替代bianhao,gender替代sex) - 数据类型:编号改为字符串类型,保留前导零
- 输出方式:使用DOM操作替代
document.write(),通过模板字符串构建页面结构 - 用户体验:将弹窗提示改为页面内状态更新,添加交互按钮
- 代码组织:将渲染逻辑封装为函数,提高可维护性
- 样式美化:添加CSS样式,使展示更美观
案例2:人类对象数组创建与遍历
需求说明
创建包含3名人员信息的对象数组,并遍历展示所有人员信息。
原始代码实现
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>人员对象数组</title>
<script>
var persons=[
{'bianhao':007,'name':'诗书画唱1','age':20},
{'bianhao':666,'name':'诗书画唱2','age':21},
{'bianhao':233,'name':'诗书画唱3','age':22},
];
for(var i of persons){
for(var j in i){
document.write(i[j]+" ");
}
document.write("<br>");
}
</script>
</head>
<body>
</body>
</html>
原始代码解析
- 创建了包含3个人员对象的数组
- 使用
for...of遍历数组中的每个对象 - 使用
for...in遍历每个对象的属性 - 通过
document.write()输出属性值,使用 分隔
存在的问题
- 缺乏表头信息,用户无法直观理解各数值含义
- 输出格式简陋,数据排列不整齐
- 同样存在编号前导零丢失问题
- 直接使用
document.write()不利于样式控制
优化方案
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>优化后的人员对象数组</title>
<style>
.persons-table {
border-collapse: collapse;
width: 80%;
max-width: 600px;
margin: 20px;
border: 1px solid #ddd;
}
.persons-table th, .persons-table td {
padding: 12px;
text-align: left;
border-bottom: 1px solid #ddd;
}
.persons-table th {
background-color: #f2f2f2;
font-weight: bold;
}
.persons-table tr:hover {
background-color: #f5f5f5;
}
</style>
</head>
<body>
<table class="persons-table" id="personsTable">
<!-- 表格内容将通过JS动态生成 -->
</table>
<script>
// 人员数据数组,使用规范命名和字符串编号
const persons = [
{ id: '007', name: '诗书画唱1', age: 20 },
{ id: '666', name: '诗书画唱2', age: 21 },
{ id: '233', name: '诗书画唱3', age: 22 }
];
// 渲染人员表格
function renderPersonsTable(persons) {
const table = document.getElementById('personsTable');
// 创建表头
const thead = document.createElement('thead');
thead.innerHTML = `
<tr>
<th>编号</th>
<th>姓名</th>
<th>年龄</th>
</tr>
`;
table.appendChild(thead);
// 创建表体并添加数据行
const tbody = document.createElement('tbody');
// 使用forEach方法遍历数组,更现代的写法
persons.forEach(person => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${person.id}</td>
<td>${person.name}</td>
<td>${person.age}</td>
`;
tbody.appendChild(row);
});
table.appendChild(tbody);
}
// 页面加载完成后渲染表格
window.onload = function() {
renderPersonsTable(persons);
};
</script>
</body>
</html>
优化点说明
- 数据结构:统一使用规范的属性命名,编号改为字符串
- 遍历方式:使用
forEach方法遍历数组,代码更简洁清晰 - 展示方式:使用表格展示数据,添加表头,提高可读性
- 样式美化:添加CSS样式,包括hover效果,提升用户体验
- 代码组织:将渲染逻辑封装为函数,便于维护和复用
- DOM操作:通过创建DOM元素构建表格,而非直接写入文档
案例3:商品构造函数与总价计算
需求说明
创建商品构造函数,实例化3件商品并放入数组,计算并展示商品总价格。
原始代码实现
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>商品总价计算</title>
<script>
var shangPin = function(bianhao, name, price, num) {
this.bianhao = bianhao;
this.name = name;
this.price = price;
this.num = num;
}
var shangPinShuZu = [
new shangPin(1,'苹果', 2, 5),
new shangPin(2,'香蕉', 5, 2),
new shangPin(3, 'CD', 10, 1)
];
alert("计算总价格为:"+jiSuanZongJiaGe(shangPinShuZu));
function jiSuanZongJiaGe(shangPinShuZu) {
var zongJiaGe = 0;
for(var i of shangPinShuZu) {
var meiGeShangPinJiaGe = (i.price * i.num);
zongJiaGe += meiGeShangPinJiaGe;
}
return zongJiaGe;
}
</script>
</head>
<body>
</body>
</html>
原始代码解析
- 使用构造函数创建
shangPin对象类型 - 实例化3个商品对象并存储在数组中
- 定义
jiSuanZongJiaGe函数计算总价 - 通过弹窗展示计算结果
存在的问题
- 构造函数命名不规范(应使用 PascalCase 命名法)
- 仅通过弹窗展示结果,用户体验不佳
- 未展示商品列表信息,用户无法核对
- 变量命名使用拼音,不符合规范
- 缺乏必要的格式处理(如价格保留两位小数)
优化方案
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>商品总价计算</title>
<style>
.product-container {
margin: 20px;
max-width: 800px;
}
.product-table {
border-collapse: collapse;
width: 100%;
margin-bottom: 20px;
}
.product-table th, .product-table td {
border: 1px solid #ddd;
padding: 12px;
text-align: left;
}
.product-table th {
background-color: #f2f2f2;
}
.total-price {
font-size: 18px;
font-weight: bold;
color: #e74c3c;
padding: 10px;
border: 1px solid #eee;
display: inline-block;
}
</style>
</head>
<body>
<div class="product-container">
<h2>商品列表</h2>
<table class="product-table" id="productTable"></table>
<div id="totalPriceContainer"></div>
</div>
<script>
// 使用ES6 class语法,更清晰的构造函数
class Product {
constructor(id, name, price, quantity) {
this.id = id;
this.name = name;
this.price = price;
this.quantity = quantity;
}
// 计算单个商品总价的方法
getTotalPrice() {
return this.price * this.quantity;
}
}
// 创建商品数组
const products = [
new Product(1, '苹果', 2, 5),
new Product(2, '香蕉', 5, 2),
new Product(3, 'CD', 10, 1)
];
// 计算所有商品的总价
function calculateTotalPrice(products) {
// 使用reduce方法计算总价,更函数式的写法
return products.reduce((total, product) => {
return total + product.getTotalPrice();
}, 0);
}
// 渲染商品列表和总价
function renderProducts() {
const table = document.getElementById('productTable');
const totalContainer = document.getElementById('totalPriceContainer');
// 创建表头
table.innerHTML = `
<tr>
<th>编号</th>
<th>商品名称</th>
<th>单价(元)</th>
<th>数量</th>
<th>小计(元)</th>
</tr>
`;
// 添加商品行
products.forEach(product => {
const row = document.createElement('tr');
const subtotal = product.getTotalPrice();
row.innerHTML = `
<td>${product.id}</td>
<td>${product.name}</td>
<td>${product.price.toFixed(2)}</td>
<td>${product.quantity}</td>
<td>${subtotal.toFixed(2)}</td>
`;
table.appendChild(row);
});
// 展示总价
const totalPrice = calculateTotalPrice(products);
totalContainer.innerHTML = `
<div class="total-price">
商品总价:${totalPrice.toFixed(2)}元
</div>
`;
}
// 页面加载完成后渲染
window.onload = function() {
renderProducts();
};
</script>
</body>
</html>
优化点说明
- 构造函数:使用ES6的
class语法,更清晰的面向对象结构 - 命名规范:使用英文命名且遵循规范(PascalCase 用于类,camelCase 用于方法和属性)
- 方法封装:在类中添加
getTotalPrice方法计算单个商品总价 - 计算方式:使用
reduce方法计算总价,更符合函数式编程风格 - 展示方式:通过表格展示完整商品信息,包括单价、数量和小计
- 格式处理:使用
toFixed(2)确保价格保留两位小数 - 用户体验:在页面中展示结果而非弹窗,提供完整的视觉信息
扩展题:对象操作进阶技巧
扩展1:对象控制台输出与方法优化
原始代码实现
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>对象控制台输出</title>
<script>
// 第一种创建对象方法:直接创建
var duiXiang1={'bianhao':1,'name':'诗书画唱' , 'age':19,'sex':'男'};
// 第二种创建对象方法:使用new创建
var duiXiang2=new Object();
duiXiang2.bianhao=2;
duiXiang2.name='诗书画唱SSHC';
duiXiang2.age=19;
duiXiang2.sex='男';
duiXiang2.gongneng=function(){
alert(this.name+"的功能是吃饭");
document.write(this.name+"的功能是吃饭");
}
console.log(duiXiang1);
console.log(duiXiang2);
window.onload=function() {
duiXiang2.gongneng();
}
</script>
</head>
<body>
</body>
</html>
优化方案
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>对象控制台输出优化</title>
<style>
.info-box {
margin: 20px;
padding: 15px;
border: 1px solid #ccc;
border-radius: 5px;
}
.hint {
color: #666;
font-style: italic;
}
</style>
</head>
<body>
<div class="info-box">
<h3>对象调试演示</h3>
<p>请打开浏览器控制台(F12)查看对象信息</p>
<p class="hint">提示:在控制台中可以展开对象,查看其属性和方法</p>
<div id="actionResult"></div>
</div>
<script>
// 使用对象字面量创建(推荐方式)
const person1 = {
id: 1,
name: '诗书画唱',
age: 19,
gender: '男',
// 重写toString方法,便于日志输出
toString() {
return `${this.name} (${this.id}): ${this.age}岁, ${this.gender}`;
}
};
// 使用Object.create创建对象(适合需要原型继承的场景)
const person2 = Object.create(null, {
id: { value: 2, writable: true },
name: { value: '诗书画唱SSHC', writable: true },
age: { value: 19, writable: true },
gender: { value: '男', writable: true },
// 吃饭方法
eat: {
value: function() {
const resultElement = document.getElementById('actionResult');
resultElement.textContent = `${this.name}正在吃饭`;
// 在控制台输出详细信息
console.log(`${new Date().toLocaleTimeString()}: ${this.name}执行了吃饭动作`);
}
}
});
// 控制台输出优化
console.group('人员对象信息');
console.log('person1 对象:', person1);
console.log('person1 字符串表示:', person1.toString());
console.log('person2 对象:', person2);
console.dir(person2); // 更详细的对象结构展示
console.groupEnd();
// 页面加载后执行方法
window.onload = function() {
// 添加按钮触发动作,而非自动执行
const button = document.createElement('button');
button.textContent = '执行吃饭动作';
button.onclick = () => person2.eat();
document.body.appendChild(button);
};
</script>
</body>
</html>
扩展1.1:对象属性的添加与删除
实现代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>对象属性操作</title>
<style>
.container {
margin: 20px;
}
.object-display {
padding: 15px;
background-color: #f8f9fa;
border-radius: 5px;
margin: 10px 0;
white-space: pre-wrap;
}
button {
margin: 5px;
padding: 6px 12px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="container">
<h3>对象属性添加与删除演示</h3>
<div>
<button onclick="addProperty()">添加属性</button>
<button onclick="deleteProperty()">删除属性</button>
<button onclick="modifyProperty()">修改属性</button>
<button onclick="checkProperty()">检查属性是否存在</button>
</div>
<h4>当前对象:</h4>
<div class="object-display" id="objectDisplay"></div>
<div id="message"></div>
</div>
<script>
// 初始对象
let person = {
id: 1,
name: '诗书画唱',
age: 19,
gender: '男'
};
// 显示对象当前状态
function displayObject() {
const displayElement = document.getElementById('objectDisplay');
// 格式化输出,便于阅读
displayElement.textContent = JSON.stringify(person, null, 2);
}
// 添加属性
function addProperty() {
// 检查属性是否已存在
if (!person.address) {
person.address = '北京市';
showMessage('已添加address属性');
} else if (!person.hobby) {
person.hobby = '阅读';
showMessage('已添加hobby属性');
} else {
showMessage('所有可选属性已添加');
}
displayObject();
}
// 删除属性
function deleteProperty() {
// 删除属性的两种方式
if (person.age) {
delete person.age;
showMessage('已删除age属性');
} else if (person.gender) {
delete person['gender'];
showMessage('已删除gender属性');
} else {
showMessage('没有可删除的属性');
}
displayObject();
}
// 修改属性
function modifyProperty() {
person.age = person.age ? person.age + 1 : 20;
showMessage(`已更新age属性为: ${person.age}`);
displayObject();
}
// 检查属性是否存在
function checkProperty() {
const hasId = 'id' in person;
const hasAddress = 'address' in person;
showMessage(`id属性存在: ${hasId}, address属性存在: ${hasAddress}`);
}
// 显示操作消息
function showMessage(text) {
const messageElement = document.getElementById('message');
messageElement.textContent = text;
}
// 初始化显示
window.onload = function() {
displayObject();
};
</script>
</body>
</html>
扩展1.2:JavaScript数组遍历方法详解
实现代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>数组遍历方法详解</title>
<style>
.container {
margin: 20px;
max-width: 800px;
}
.method-section {
margin-bottom: 30px;
padding: 15px;
border: 1px solid #eee;
border-radius: 5px;
}
.result {
background-color: #f8f9fa;
padding: 10px;
margin-top: 10px;
border-radius: 4px;
white-space: pre-wrap;
}
button {
padding: 6px 12px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="container">
<h2>JavaScript数组遍历方法对比</h2>
<div class="method-section">
<h3>1. for循环遍历</h3>
<button onclick="traverseWithFor()">执行for循环遍历</button>
<div class="result" id="forResult"></div>
</div>
<div class="method-section">
<h3>2. for...of遍历</h3>
<button onclick="traverseWithForOf()">执行for...of遍历</button>
<div class="result" id="forOfResult"></div>
</div>
<div class="method-section">
<h3>3. forEach遍历</h3>
<button onclick="traverseWithForEach()">执行forEach遍历</button>
<div class="result" id="forEachResult"></div>
</div>
<div class="method-section">
<h3>4. map遍历(返回新数组)</h3>
<button onclick="traverseWithMap()">执行map遍历</button>
<div class="result" id="mapResult"></div>
</div>
<div class="method-section">
<h3>5. filter遍历(筛选元素)</h3>
<button onclick="traverseWithFilter()">执行filter遍历</button>
<div class="result" id="filterResult"></div>
</div>
</div>
<script>
// 人员数据数组
const persons = [
{ id: 1, name: '诗书画唱1', age: 19 },
{ id: 2, name: '诗书画唱2', age: 22 },
{ id: 3, name: '诗书画唱3', age: 25 }
];
// 1. for循环遍历
function traverseWithFor() {
const result = [];
for (let i = 0; i < persons.length; i++) {
result.push(`[${i}] ${persons[i].name}, ${persons[i].age}岁`);
}
document.getElementById('forResult').textContent = result.join('\n');
}
// 2. for...of遍历
function traverseWithForOf() {
const result = [];
for (const person of persons) {
result.push(`${person.name}, ${person.age}岁`);
}
document.getElementById('forOfResult').textContent = result.join('\n');
}
// 3. forEach遍历
function traverseWithForEach() {
const result = [];
persons.forEach((person, index) => {
result.push(`[${index}] ${person.name}, ${person.age}岁`);
});
document.getElementById('forEachResult').textContent = result.join('\n');
}
// 4. map遍历(返回新数组)
function traverseWithMap() {
// map返回一个新数组,包含转换后的值
const mapped = persons.map(person => {
return {
fullInfo: `${person.name} (ID: ${person.id})`,
ageGroup: person.age < 20 ? '青年' : '成年'
};
});
document.getElementById('mapResult').textContent = JSON.stringify(mapped, null, 2);
}
// 5. filter遍历(筛选元素)
function traverseWithFilter() {
// filter返回符合条件的元素组成的新数组
const adults = persons.filter(person => person.age >= 20);
document.getElementById('filterResult').textContent = JSON.stringify(adults, null, 2);
}
</script>
</body>
</html>
总结与进阶建议
通过对以上案例的解析与优化,我们可以总结出JavaScript对象与数组操作的最佳实践:
- 命名规范:使用有意义的英文名称,遵循PascalCase(类)和camelCase(方法、属性)命名法
- 变量声明:优先使用
const和let,避免使用var,明确变量的可变性 - 对象创建:
- 简单对象推荐使用对象字面量
{} - 复杂对象或需要多次实例化时使用
class - 避免使用
new Object()创建对象
- 简单对象推荐使用对象字面量
- 数组遍历:
- 简单遍历推荐使用
forEach - 需要返回新数组时使用
map - 需要筛选元素时使用
filter - 需要计算累加结果时使用
reduce
- 简单遍历推荐使用
- DOM操作:避免使用
document.write(),通过createElement和textContent等方法操作DOM - 代码组织:将功能封装为函数,提高复用性和可维护性
进阶学习建议
- 学习ES6+更多特性:箭头函数、解构赋值、展开运算符等
- 掌握数组高级方法:
find(),some(),every(),sort()等 - 学习对象的原型与继承机制
- 了解Immutable数据处理理念,避免直接修改对象
- 学习TypeScript,为对象和数组添加类型定义,提高代码健壮性
通过不断实践这些技巧,你将能够写出更规范、高效、可维护的JavaScript代码,为构建复杂前端应用打下坚实基础。
更多推荐


所有评论(0)