函数定义
约 620 字大约 2 分钟
2026-03-31
思考
函数定义有哪些方法,它们有什么区别?
1. 函数声明(具名函数)
console.log(sum(1, 2)); // 可以提前调用
function sum(a, b) {
console.log(arguments); // [Arguments] { '0': 1, '1': 2 }
return a + b;
}
// 特点:
console.log(sum(1, 2)); // 3
console.log(sum.name); // "sum"关键特性:
- 函数提升:可以在声明前调用
- 有自己的
name属性 - 拥有
arguments对象 - 有自己的
this绑定(根据直接调用它的方式动态绑定)
2. 函数表达式
// 匿名函数表达式
const multiply = function (a, b) {
return a * b;
};
// 命名函数表达式(推荐)
const divide = function div(a, b) {
return a / b;
};关键特性:
- 无函数提升:必须先定义后使用
- 可匿名也可命名
- 适合作为回调函数、IIFE(立即调用函数表达式)
- this 绑定根据调用方式动态确定
// console.log(square(5)); // ReferenceError - 不能提前调用
const square = function (n) {
return n * n;
};
console.log(square(5)); // 25 - 必须先定义
// 定义时可以立即执行函数,末尾添加括号,表示立即执行
const test = (function IIFE() {
console.log(1);
})();3. 箭头函数 (ES6+)
// 基本语法
const add = (a, b) => a + b;
// 多参数需要括号
const greet = (name, age) => `Hello ${name}, age ${age}`;
// 单参数可省略括号
const double = (n) => n * 2;
// 函数体多条语句需要大括号和 return
const calculate = (a, b) => {
const sum = a + b;
const product = a * b;
return { sum, product };
};关键特性:
- 无函数提升
- 没有自己的
this(继承自父作用域,定义时就确定) - 没有
arguments对象 - 不能作为构造函数(不能用
new) - 没有
prototype属性
// this 绑定差异
const obj = {
value: 42,
regular: function () {
console.log(this.value); // 42 - this 指向 obj
},
arrow: () => {
console.log(this.value); // undefined - this 指向外层(全局)
},
};
obj.regular(); // 42
obj.arrow(); // undefined4. Function 构造函数
const dynamicFunc = new Function("a", "b", "return a + b");
console.log(dynamicFunc(2, 3)); // 5
// 从字符串动态创建
const operation = "multiply";
const funcBody = operation === "add" ? "return a + b" : "return a * b";
const customFunc = new Function("a", "b", funcBody);关键特性:
- 完全动态创建
- 性能差(每次都会解析字符串)
- 安全问题(可能执行恶意代码)
- 无法访问外层作用域变量(只能在全局作用域运行)
5. 生成器函数
function* numberGenerator() {
yield 1;
yield 2;
yield 3;
}
const gen = numberGenerator();
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2关键特性:
- 可暂停和恢复执行
- 返回生成器对象,不是直接返回值
- 使用
yield关键字