JavaScript 进阶:玩转函数、数组与对象
本篇聊聊 JavaScript 的核心内容:函数、数组和对象。如果把编程比作盖房子,基础语法就是砖头,而函数、数组和对象就是你的设计图和建筑结构。掌握了这三样,你才能真正开始处理复杂的业务逻辑。
# 一、函数:代码的执行引擎
一个函数本质上就是一个可重复使用的代码块,专门用来执行特定的任务。与其为了重复逻辑写五十遍代码,不如把它们封装进函数里,想用的时候随叫随到。
我们可以把函数想象成一台咖啡机:你投入原材料(水和咖啡豆),机器内部完成转换,最后吐出你要的咖啡。
# 1、为什么要用函数?
假设你正在写一个健身 App,需要计算不同动作的总训练量(组数 × 次数)。
如果不使用函数,你的代码会变得非常冗长且难以维护:
let deadliftSets = 4, deadliftReps = 5;
let deadliftVolume = deadliftSets * deadliftReps;
console.log("Deadlift Volume: " + deadliftVolume);
let squatSets = 5, squatReps = 5;
let squatVolume = squatSets * squatReps;
console.log("Squat Volume: " + squatVolume);
// 如果你有 20 个动作,你得重复写几十遍这种逻辑,简直是折磨
使用函数后,事情就变得优雅多了:
function calculateVolume(exercise, sets, reps) {
let total = sets * reps;
return `${exercise} Volume: ${total}`;
}
console.log(calculateVolume("Deadlift", 4, 5)); // Deadlift Volume: 20
console.log(calculateVolume("Squat", 5, 5)); // Squat Volume: 25
用函数有三个实实在在的好处:
代码复用:写一次,用一万次。
逻辑清晰:看到
calculateVolume你就知道在算体积,而不是盯着一堆数字发呆。易于维护:万一计算公式变了,你只需要改函数内部的一行代码,而不是满大街去找报错。
# 2、函数的几种写法
在 JavaScript 中,定义函数有几种主流方式,这里我带你梳理一下。
# 函数声明 (Function Declaration)
这是最传统的写法:
function welcomeDev(username) {
console.log("Welcome to the system, " + username);
}
welcomeDev("Abhay");
这里的关键在于:函数声明会被提升 (Hoisting)。这意味着你可以在定义函数之前就调用它,JavaScript 引擎在执行代码前会先扫描一遍所有的声明。
# 函数表达式 (Function Expression)
你也可以把函数赋值给一个变量:
const connectDatabase = function(dbName) {
console.log("Connected to: " + dbName);
};
connectDatabase("Main_App_DB");
注意:函数表达式不会被提升。如果你在赋值之前就调用它,程序会直接报错。
# 箭头函数 (Arrow Functions)
这是 ES6 引入的最现代、最简洁的写法,也是现在开发中最推荐的:
// 普通写法
const calculateMacros = (protein, carbs) => {
return protein + carbs;
};
// 极致简化:如果只有一行逻辑,可以省略大括号和 `return`
const multiply = (a, b) => a * b;
// 如果只有一个参数,甚至可以省略圆括号
const doubleReps = reps => reps * 2;
# 3、参数与返回值
函数可以通过“参数”接收输入,通过 return 返回结果。
这里有个细节要注意:如果你在函数里写了 return,函数会立即结束,后面的代码会被直接跳过。如果一个函数没有明确写 return,它的默认返回值是 undefined。
此外,我们还可以利用 剩余参数 (Rest Parameters) 来处理不确定数量的输入:
function sumWeights(...weights) {
let total = 0;
for (let w of weights) {
total += w;
}
return total;
}
console.log(sumWeights(45, 25, 10)); // 80
# 二、数组:管理数据的清单
数组就像是一个带编号的储物柜,你可以按顺序存放各种数据。在 JavaScript 中,数组的索引是从 0 开始的。
# 1、数组的操作:变动 vs 不变
处理数组时,你会遇到两种方法。一种是直接修改原数组(Mutating),另一种是返回一个全新的数组(Non-Mutating)。
为了方便理解,我整理了这个对比表:
| 方法 | 是否修改原数组 | 核心功能 |
|---|---|---|
push / pop | 是 | 在末尾添加/删除元素 |
unshift / shift | 是 | 在开头添加/删除元素 |
splice | 是 | 在指定位置增删元素 |
slice | 否 | 截取部分元素并返回新数组 |
concat | 否 | 合并多个数组 |
实战小技巧:
使用 sort() 对数字排序时千万要小心,默认它是按字符串顺序排的。比如 [10, 1, 5].sort() 会得到 [1, 10, 5]。正确的写法是传入一个比较函数:sort((a, b) => a - b)。
# 2、高阶迭代方法:开发者的“四大神技”
如果你想在面试或实际开发中显得专业,这四个数组方法必须烂熟于心:
forEach:单纯的遍历,不返回新数组。map:最常用的方法,将数组中的每个元素按规则转换,并返回一个新数组。filter:过滤器,只保留符合条件的元素。reduce:累加器,把数组里的所有值“压缩”成一个值(比如求和)。
const prices = [100, 200, 300];
// 每一个都打 9 折
const discounted = prices.map(p => p * 0.9);
// 只保留大于 150 的
const expensive = prices.filter(p => p > 150);
# 3、解构与展开
现代 JavaScript 提供了非常爽的语法来处理数组:
解构 (Destructuring):快速提取数组元素。
展开运算符 (
...):快速合并数组。
const techStack = ["React", "Vue", "Angular"];
const [first, second] = techStack; // first = "React", second = "Vue"
const moreTech = [...techStack, "Docker"]; // 直接合并
# 三、对象:描述现实世界的实体
如果说数组是“列表”,那么对象就是“详情页”。它通过 key-value(键值对)的形式来描述一个实体的属性。
# 1、访问与修改
你可以通过点号 . 或者方括号 [] 来访问属性:
const developer = {
name: "Lin",
age: 25
};
console.log(developer.name); // 点号写法(首选)
console.log(developer["age"]); // 方括号写法(适用于动态 key)
// 修改与删除
developer.location = "Beijing"; // 添加新属性
delete developer.age; // 删除属性
# 2、this 关键字与方法
当函数成为对象的一个属性时,它就叫“方法”。在方法内部,this 指向的是这个对象本身。
const user = {
handle: "Coder_01",
login() {
console.log(`${this.handle} has logged in.`);
}
};
user.login();
# 3、Array vs Object:到底用哪个?
这是一个经典的面试题。到底该选数组还是对象?我的建议是看你的数据形态。
| 特性 | 数组 (Array) | 对象 (Object) |
|---|---|---|
| 核心逻辑 | 有序的数据集合 | 无序的键值对集合 |
| 访问方式 | 通过数字索引 (index) | 通过属性名 (key) |
| 典型场景 | 任务列表、商品列表、用户名单 | 用户信息、配置参数、产品详情 |
实际工程中的终极形态: 在现代开发中,我们通常会结合使用两者:“对象的数组”。比如一个 API 返回的商品列表,其实就是一个数组,数组里的每一个元素都是一个包含多个属性的对象。
const products = [
{ id: 1, name: "Laptop", price: 999 },
{ id: 2, name: "Mouse", price: 49 }
];
// 查找所有价格大于 50 的商品名
const cheapItems = products
.filter(p => p.price < 100)
.map(p => p.name);
掌握了这套组合拳,你就已经跨过了 JavaScript 最核心的门槛。
