JavaScript函数进阶 - 实用指南
🔥 必须掌握:Rest参数与Spread语法
Rest参数(收集剩余参数)
// 传统方式:arguments对象(不推荐)
function oldWay() {
console.log(arguments); // 类数组对象,不够好用
}
// 现代方式:Rest参数(推荐)
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
// 混合使用
function greet(greeting, ...names) {
return `${greeting} ${names.join(', ')}!`;
}
console.log(greet("Hello", "张三", "李四", "王五")); // "Hello 张三, 李四, 王五!"
// 实际应用:通用日志函数
function log(level, ...messages) {
console.log(`[${level}]`, ...messages);
}
log("INFO", "用户登录", "ID:", 123); // [INFO] 用户登录 ID: 123
Spread语法(展开语法)
// 数组展开
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
// 合并数组
let combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]
// 复制数组
let copy = [...arr1]; // [1, 2, 3]
// 找最大值
console.log(Math.max(...arr1)); // 3
// 对象展开(非常实用!)
let user = {name: "张三", age: 30};
let userWithCity = {...user, city: "北京"}; // {name: "张三", age: 30, city: "北京"}
// 覆盖属性
let updatedUser = {...user, age: 31}; // {name: "张三", age: 31}
// 实际应用:React/Vue中的状态更新
function updateUserProfile(currentUser, updates) {
return {...currentUser, ...updates, updatedAt: new Date()};
}
🔥 必须掌握:箭头函数深入理解
箭头函数 vs 普通函数
// 普通函数
function normalFunction(x) {
return x * 2;
}
// 箭头函数
const arrowFunction = (x) => x * 2;
// 简写形式
const double = x => x * 2; // 单参数可省略括号
const add = (a, b) => a + b; // 单表达式可省略return
const createUser = name => ({ // 返回对象需要括号
name: name,
createdAt: new Date()
});
this绑定的重要区别
const obj = {
name: "张三",
// 普通方法:this指向调用对象
regularMethod: function() {
console.log("普通方法:", this.name); // "张三"
// 内部函数的this指向问题
setTimeout(function() {
console.log("普通函数内部:", this.name); // undefined
}, 100);
// 箭头函数继承外层this
setTimeout(() => {
console.log("箭头函数内部:", this.name); // "张三"
}, 100);
},
// 箭头函数方法:this指向外层(注意陷阱!)
arrowMethod: () => {
console.log("箭头方法:", this.name); // undefined(this不是obj)
}
};
obj.regularMethod();
obj.arrowMethod();
实际应用场景
// Vue/React事件处理
class TodoApp {
constructor() {
this.todos = [];
}
// 箭头函数自动绑定this,不需要bind
addTodo = (text) => {
this.todos.push({
id: Date.now(),
text: text,
completed: false
});
}
// 数组处理中的箭头函数
getCompletedTodos = () => {
return this.todos.filter(todo => todo.completed);
}
}
// 数组处理(最常用)
const users = [
{name: "张三", age: 25},
{name: "李四", age: 30},
{name: "王五", age: 35}
];
const adultNames = users
.filter(user => user.age >= 30)
.map(user => user.name);
🔄 异步编程基础
注意: setTimeout/setInterval的详细用法和事件循环机制请参考
js-event-loop-complete-analysis.md
完整分析文档。
这里只保留与函数相关的核心概念:
// 在异步回调中保持this绑定
const obj = {
name: "示例对象",
// 普通函数:this可能丢失
regularCallback: function() {
setTimeout(function() {
console.log(this.name); // undefined
}, 100);
},
// 箭头函数:自动绑定this
arrowCallback: function() {
setTimeout(() => {
console.log(this.name); // "示例对象"
}, 100);
}
};
⚡ 重要理解:变量作用域和闭包
作用域基础
// 全局作用域
let globalVar = "我是全局变量";
function outerFunction() {
// 函数作用域
let outerVar = "我是外层变量";
function innerFunction() {
// 内层作用域
let innerVar = "我是内层变量";
// 可以访问所有外层变量
console.log(globalVar); // ✓
console.log(outerVar); // ✓
console.log(innerVar); // ✓
}
innerFunction();
// console.log(innerVar); // ✗ 无法访问内层变量
}
闭包的实际应用
// 数据私有化
function createCounter() {
let count = 0; // 私有变量
return {
increment: () => ++count,
decrement: () => --count,
getValue: () => count
};
}
const counter = createCounter();
console.log(counter.getValue()); // 0
counter.increment();
console.log(counter.getValue()); // 1
// count变量无法直接访问,实现了数据封装
// 模块模式
const userModule = (function() {
let users = []; // 私有数据
return {
addUser: function(user) {
users.push(user);
},
getUsers: function() {
return [...users]; // 返回副本,保护原数据
},
getUserCount: function() {
return users.length;
}
};
})();
userModule.addUser({name: "张三"});
console.log(userModule.getUserCount()); // 1
⚡ 重要理解:函数绑定
call、apply、bind的区别
const person = {
name: "张三",
greet: function(greeting, punctuation) {
return `${greeting}, 我是${this.name}${punctuation}`;
}
};
const anotherPerson = {name: "李四"};
// call:立即调用,参数逐个传递
console.log(person.greet.call(anotherPerson, "你好", "!"));
// "你好, 我是李四!"
// apply:立即调用,参数用数组传递
console.log(person.greet.apply(anotherPerson, ["嗨", "~"]));
// "嗨, 我是李四~"
// bind:返回新函数,不立即调用
const boundGreet = person.greet.bind(anotherPerson);
console.log(boundGreet("欢迎", "。"));
// "欢迎, 我是李四。"
实际应用场景
// 事件处理器中保持this
class Button {
constructor(element) {
this.element = element;
this.clickCount = 0;
// 绑定this,确保事件处理器中this指向正确
this.element.addEventListener('click', this.handleClick.bind(this));
}
handleClick() {
this.clickCount++;
console.log(`按钮被点击了 ${this.clickCount} 次`);
}
}
// 借用方法
const arrayLike = {0: 'a', 1: 'b', 2: 'c', length: 3};
const realArray = Array.prototype.slice.call(arrayLike);// 借用了 slice 方法
console.log(realArray); // ['a', 'b', 'c']
📚 了解即可(现在可跳过)
递归和堆栈
// 了解概念即可,实际开发中循环更常用
function factorial(n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
var的问题
// 了解即可:现代开发用let/const,不用var
var oldWay = "有作用域提升和其他问题";
let modernWay = "推荐使用";
const constantWay = "不可重新赋值";
全局对象
// 了解即可:window(浏览器)、global(Node.js)
// 现代模块化开发很少直接操作全局对象
函数对象和NFE
// 了解即可:函数的name、length属性等
function example() {}
console.log(example.name); // "example"
装饰器模式
// 了解即可:高级模式,框架内部使用
function decorator(func) {
return function(...args) {
console.log('调用前');
const result = func.apply(this, args);
console.log('调用后');
return result;
};
}
实际开发模式
现代函数式编程风格
// 数据处理管道
const processUsers = (users) =>
users
.filter(user => user.active)
.map(user => ({
...user,
displayName: user.name.toUpperCase()
}))
.sort((a, b) => a.displayName.localeCompare(b.displayName));
// 异步操作
const fetchUserData = async (userId) => {
try {
const response = await fetch(`/api/users/${userId}`);
return await response.json();
} catch (error) {
console.error('获取用户数据失败:', error);
return null;
}
};
// 事件处理
const handleFormSubmit = async (formData) => {
const result = await submitForm(formData);
if (result.success) {
showSuccessMessage();
} else {
showErrorMessage(result.error);
}
};
学习建议
现在重点掌握
Rest/Spread语法 - 现代JS核心特性
箭头函数 - 简洁语法,理解this绑定
setTimeout/setInterval - 异步编程基础
闭包基本概念 - 理解作用域和数据封装
实践方向
用箭头函数重写现有代码
练习数组的map/filter/reduce
实现简单的防抖函数
理解Vue/React中的this绑定
暂时跳过
复杂的闭包应用
装饰器模式
函数的高级特性
这些内容掌握后,你就具备了现代JavaScript函数编程的核心技能,足以应对大部分开发场景!