第三十一天:箭头函数 — 代码简洁的关键
蜗牛往上爬 · 前端工业可视化学习笔记 第 31 篇
箭头函数(=>)是 ES6 的标志性语法。它让回调函数变得极简,还解决了 this 指向的难题。今天学箭头函数的各种写法、与普通函数的区别,特别是"没有自己的 this"这个核心特性——第 8 周的 this 丢失问题终于有了标准解法。
目录
一、基本语法:从 function 到 =>
// ES5
function add(a, b) { return a + b; }
// ES6 箭头函数
const add = (a, b) => a + b;
语法演变:
// 完整写法
const fn1 = (a, b) => { return a + b; };
// 单表达式:省略 {} 和 return(隐式返回)
const fn2 = (a, b) => a + b;
// 单参数:省略括号
const fn3 = x => x * 2;
// 无参数:必须写空括号
const fn4 = () => console.log("Hi");
// ⭐ 返回对象:必须加括号(否则 {} 被当作函数体)
const fn5 = () => ({ id: "CNC-001" });
二、箭头函数配合数组方法
这是箭头函数最常用的场景——回调变得一目了然:
const temps = [65, 42, 38, 55, 70];
const double = temps.map(t => t * 2); // 转换
const hot = temps.filter(t => t > 50); // 筛选
const sum = temps.reduce((s, t) => s + t, 0); // 聚合
// 对象数组 + 解构参数
const deviceList = [
{ id: "CNC-001", temp: 65, online: true },
{ id: "AGV-002", temp: 42, online: false },
{ id: "ARM-003", temp: 38, online: true }
];
// 在线设备的 id(链式)
const onlineIds = deviceList
.filter(d => d.online)
.map(d => d.id);
// ["CNC-001", "ARM-003"]
// 解构参数直接取字段
const names = deviceList.map(({ id }) => id);
// ["CNC-001", "AGV-002", "ARM-003"]
对比 ES5:
// ES5:啰嗦
deviceList.filter(function (d) { return d.online; })
.map(function (d) { return d.id; });
// ES6:简洁
deviceList.filter(d => d.online).map(d => d.id);
三、没有自己的 this(核心)
箭头函数不绑定 this,它的 this 继承自外层作用域。这解决了"this 丢失"的经典问题:
const device = {
name: "CNC-001",
temps: [65, 70, 75],
factor: 2,
// ❌ ES5:回调里 this 丢失(是 undefined)
averageES5: function () {
return this.temps.map(function (t) {
return t * this.factor; // ❌ this 不是 device
});
},
// ✅ ES6:箭头函数继承外层 this(即 device)
averageES6: function () {
return this.temps.map(t => t * this.factor); // ✅ this 是 device
}
};
console.log(device.averageES6()); // [130, 140, 150]
原理:averageES6 是普通函数,this 指向 device;内部的箭头函数没有自己的 this,所以"借用"外层——指向 device。第 8 周用 var self = this 的补救写法,现在不需要了。
四、箭头函数 vs 普通函数
// 箭头函数没有 arguments → 用 rest
const fn = (...args) => console.log(args);
// 箭头函数不能 new
// new (() => {})() // ❌
// 对象方法不推荐箭头函数
const obj = {
name: "A",
bad: () => console.log(this.name), // ❌ this 不是 obj
good: function () { console.log(this.name); } // ✅
};
选型建议:回调(map/filter/事件/定时器)用箭头函数;对象方法、构造函数用普通函数。
五、默认参数值
// ES5:用 || 手动设置
function greet(name) {
name = name || "未知设备";
return "你好," + name;
}
// ES6:参数默认值(更清晰)
const greet = (name = "未知设备") => "你好," + name;
console.log(greet()); // "你好,未知设备"
console.log(greet("CNC-001")); // "你好,CNC-001"
// 默认值 + 解构 + 箭头函数(现代写法)
const render = ({ name = "未知", temp = 0 } = {}) =>
console.log(`${name}:${temp}°C`);
render({ name: "CNC-001", temp: 65 }); // "CNC-001:65°C"
六、实战:重构设备管理系统
// ===== ES5(旧)=====
var devices = [
{ id: "CNC-001", name: "数控机床", temp: 65 },
{ id: "AGV-002", name: "搬运机器人", temp: 42 }
];
function render(filterText) {
var list = document.getElementById("device-list");
list.innerHTML = "";
var data = filterText ? devices.filter(function (d) {
return d.name.indexOf(filterText) !== -1;
}) : devices;
data.forEach(function (device) {
var li = document.createElement("li");
li.textContent = device.id + " - " + device.name + " - " + device.temp + "°C";
list.appendChild(li);
});
}
// ===== ES6(新)=====
const devices = [
{ id: "CNC-001", name: "数控机床", temp: 65 },
{ id: "AGV-002", name: "搬运机器人", temp: 42 }
];
const render = (filterText) => {
const list = document.getElementById("device-list");
list.innerHTML = "";
const data = filterText
? devices.filter(d => d.name.includes(filterText))
: devices;
data.forEach(({ id, name, temp }) => {
const li = document.createElement("li");
li.textContent = `${id} - ${name} - ${temp}°C`;
list.appendChild(li);
});
};
代码量几乎减半,可读性大幅提升。
七、总结
🎯 箭头函数是 ES6 的"门面"。明天学字符串扩展——模板字符串让拼接代码彻底告别
+。