4 种函数
1. 函数声明
function add(a, b) {
return a + b;
}
特点:可以提升(hoisted)—— 声明之前就能调用。
2. 函数表达式
const add = function (a, b) {
return a + b;
};
不提升,必须先声明再用。
3. 箭头函数(最常用)
const add = (a, b) => a + b;
const square = x => x * x;
const greet = name => `Hello, ${name}`;
// 多行
const compute = (a, b) => {
const sum = a + b;
return sum * 2;
};
// 返回对象要包小括号
const make = name => ({ name, ts: Date.now() });
特点:
- 没有自己的
this(继承外层) - 没有
arguments(用...args替代) - 不能用作 constructor(
new它会报错)
4. 异步函数(async)
const fetchData = async (url) => {
const r = await fetch(url);
return r.json();
};
详见 15-async-await。
参数
默认值
function greet(name = 'World') {
return `Hello, ${name}`;
}
greet(); // 'Hello, World'
greet('Alice'); // 'Hello, Alice'
Rest 参数
function sum(...nums) {
return nums.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3, 4); // 10
解构参数
function makeUser({ name, age = 18, email }) {
return { name, age, email };
}
makeUser({ name: 'alice', email: 'a@x.com' });
闭包:函数记住它的"出生环境"
function counter() {
let count = 0;
return function () {
count++;
return count;
};
}
const c = counter();
c(); // 1
c(); // 2
c(); // 3
每次调 counter() 返回的函数都独立保留自己的 count —— 这就是闭包。
实战:
// 私有计数器
const makeId = (() => {
let id = 0;
return () => ++id;
})();
makeId(); // 1
makeId(); // 2
// 防抖
function debounce(fn, ms) {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), ms);
};
}
this 的麻烦
const obj = {
name: 'Alice',
sayHi() {
console.log(`Hi, ${this.name}`);
}
};
obj.sayHi(); // Hi, Alice
const fn = obj.sayHi;
fn(); // Hi, undefined ❌(this 丢了)
// 绑定 this
const bound = obj.sayHi.bind(obj);
bound(); // Hi, Alice ✓
// 或用箭头函数避免 this 问题
const obj2 = {
name: 'Bob',
sayHi: () => console.log(`Hi, ${this.name}`) // ❌ 箭头继承外层 this
};
几个绑定方法
fn.call(obj, arg1, arg2) // 立即调用,this = obj
fn.apply(obj, [arg1, arg2]) // 同上但参数数组
const bound = fn.bind(obj) // 返回新函数,永远 this = obj
箭头 vs 普通函数 this 速记
对象方法 → 用 method shorthand(function 风格) ← 想要 this = 对象
回调函数 → 用箭头函数 ← 继承外层 this
IIFE(立即执行)
(function () {
// 内部代码立即跑
const secret = 42;
})();
// 箭头版
(() => {
// ...
})();
ES Module 时代用得少了——块级作用域 + 模块自然隔离。
函数也是值
const arr = [
a => a * 2,
a => a + 1,
a => a ** 2,
];
arr.forEach(fn => console.log(fn(5)));
// 10
// 6
// 25
坑
- 箭头函数没有
this/arguments——用...args替代 arguments - 闭包长期持有外层变量——大对象赋给闭包外层可能内存泄漏
this在不同环境(class / 对象 / 普通函数 / 严格模式)规则不同——遇到问题先console.log(this)看一眼
下一篇:对象与类。