在 JavaScript 中,函数的写法非常灵活,但核心可以分为两大场景:放在对象内部作为方法,以及放在对象外部作为独立函数。每种场景下都有几种完全等价的写法,下面为你详细梳理。
一、对象内部的函数(方法)的等价写法
当函数作为对象的属性存在时,有以下三种等价写法,运行效果完全一致:
- 具名函数表达式
javascript
const obj = {
name: "Alice",
greet: function greet() {
return "你好," + this.name;
}
};
- 函数拥有内部名称
greet,在调试时调用栈会清晰显示该名字 - 内部名仅在函数体内部可访问,方便递归调用自身
- 兼容性极好,适用于所有 JavaScript 环境
- 匿名函数表达式
javascript
const obj = {
name: "Alice",
greet: function() {
return "你好," + this.name;
}
};
- 省略了函数名,函数对象的
name属性为空字符串 - 调试时调用栈显示为
anonymous,可读性稍差 - 功能上与具名函数表达式完全相同,写法更短
- 方法简写语法(ES6+)
javascript
const obj = {
name: "Alice",
greet() {
return "你好," + this.name;
}
};
- ES6 引入的语法糖,省略了
function关键字和冒号 - 等价于匿名函数表达式,但代码更简洁、更现代
- 这是当前项目的首选写法,也是行业标准
三种写法的对比
| 写法 | 语法形式 | 函数名 | 调试友好度 | 递归便利性 | 代码简洁度 |
|---|---|---|---|---|---|
| 具名函数表达式 | greet: function greet() {} |
有内部名 | ⭐⭐⭐ | ⭐⭐⭐ | ⭐ |
| 匿名函数表达式 | greet: function() {} |
匿名 | ⭐ | ⭐ | ⭐⭐ |
| 方法简写 | greet() {} |
同属性名 | ⭐⭐ | ⭐ | ⭐⭐⭐ |
注意:箭头函数
greet: () => { ... }在对象方法中不推荐使用,因为它没有自己的this,会继承外层作用域,导致无法正常访问对象属性。
二、对象外部的函数(独立函数)的等价写法
当函数不依附于某个对象、独立存在时,主要有以下四种等价写法:
- 函数声明
javascript
function add(a, b) {
return a + b;
}
- 最经典、可读性最高的写法
- 拥有函数提升特性,可以在声明之前调用函数
- 适合定义全局通用函数、工具函数
- 不能在
if、for等块级作用域中随意声明,容易产生作用域污染
- 函数表达式
javascript
const add = function(a, b) {
return a + b;
};
- 将一个匿名函数赋值给变量,函数本身没有名称(也可使用具名函数表达式)
- 没有函数提升,必须先定义再调用
- 函数是对象,赋值给变量后通过变量名调用,与函数声明在功能上完全等价
- 适合条件性定义函数或作为回调传递
具名版本在调试和递归场景中更有优势:
javascript
const factorial = function fact(n) {
if (n <= 1) return 1;
return n * fact(n - 1); // 内部名 fact 用于递归
};
- 箭头函数(ES6+)
javascript
const add = (a, b) => a + b;
- 语法最简洁,省略了
function关键字和return - 没有自己的
this和arguments,this继承自外层作用域 - 不能作为构造函数使用(不能用
new调用) - 非常适合简短的回调函数、数组遍历、Promise 链等场景
单参数时可省略括号,多语句时需要加花括号和 return:
javascript
const double = n => n * 2; // 单参数,省略括号
const divide = (a, b) => { // 多语句,需要花括号
if (b === 0) throw new Error("除数不能为0");
return a / b;
};
- Function 构造函数(不推荐日常使用)
javascript
const add = new Function("a", "b", "return a + b");
- 通过
Function构造函数动态创建函数,所有参数均为字符串形式 - 参数写法灵活,多个参数可以分开写,也可以用逗号合并:
javascript
new Function("a", "b", "c", "return a + b + c");
new Function("a,b,c", "return a + b + c");
new Function("a,b", "c", "return a + b + c");
// 以上三种完全等价
- 缺点明显:代码可读性差、性能较低、无法使用闭包
- 仅适用于极少数需要从字符串动态生成函数的特殊场景,日常开发中几乎不用
箭头函数各种写法的详细说明
- 单参数箭头函数(最简洁)
javascript
const double = n => n * 2;
- 特点:当只有一个参数时,可以省略括号
- 适用场景:简单的单参数转换函数
- 代码简洁度:⭐⭐⭐⭐⭐(最简洁)
- 多参数箭头函数(标准形式)
javascript
const add = (a, b) => a + b;
- 特点:多个参数必须用括号包裹
- 适用场景:需要多个参数的简单计算
- 代码简洁度:⭐⭐⭐⭐
- 无参数箭头函数
javascript
const getTime = () => new Date().getTime();
- 特点:即使没有参数,也必须保留空括号
- 适用场景:不需要参数的函数,如获取当前时间、生成随机数等
- 代码简洁度:⭐⭐⭐⭐
- 多语句箭头函数
javascript
const calculate = (a, b) => {
const sum = a + b;
const product = a * b;
return { sum, product };
};
- 特点:函数体有多条语句时,需要用花括号包裹,并且需要显式return
- 适用场景:复杂的逻辑处理
- 代码简洁度:⭐⭐⭐
- 返回对象的箭头函数
javascript
const createUser = (name, age) => ({ name, age });
- 特点:直接返回对象字面量时,需要用括号包裹对象,否则会被解析为函数体
- 适用场景:工厂函数、创建配置对象等
- 代码简洁度:⭐⭐⭐
- 立即执行箭头函数
javascript
const result = ((a, b) => a + b)(3, 4); // result = 7
- 特点:箭头函数也可以立即执行
- 适用场景:需要立即执行的简单逻辑
- 代码简洁度:⭐⭐⭐
箭头函数的特点总结
- this绑定:箭头函数没有自己的this,它继承自外层作用域
- 不能作为构造函数:不能使用new关键字调用
- 没有arguments对象:需要使用rest参数(...args)替代
- 没有原型属性:箭头函数没有prototype属性
- 不能用作生成器:不能使用yield关键字
使用建议
- 简单回调:优先使用箭头函数,代码简洁
- 需要this绑定:在需要绑定外层this的场景使用箭头函数
- 对象方法:避免使用箭头函数作为对象方法(会丢失this)
- 构造函数:不要使用箭头函数作为构造函数
- 复杂逻辑:多语句时使用花括号形式,保持代码清晰
这些箭头函数的写法在实际开发中都非常常见,您可以根据具体需求选择最合适的写法。
总结对象外部函数写法对比
| 写法 | 语法形式 | 函数名 | 调试友好度 | 递归便利性 | 代码简洁度 |
|---|---|---|---|---|---|
| 函数声明 | function add(a, b) { return a + b; } |
有函数名 | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ |
| 函数表达式 | const add = function(a, b) { return a + b; } |
匿名 | ⭐ | ⭐ | ⭐⭐ |
| 具名函数表达式 | const add = function sum(a, b) { return a + b; } |
有内部名 | ⭐⭐⭐ | ⭐⭐⭐ | ⭐ |
| 箭头函数(单参数) | const add = a => a + 5; |
匿名 | ⭐ | ⭐ | ⭐⭐⭐⭐ |
| 箭头函数(多参数) | const add = (a, b) => a + b; |
匿名 | ⭐ | ⭐ | ⭐⭐⭐ |
| 箭头函数(无参数) | const greet = () => "Hello"; |
匿名 | ⭐ | ⭐ | ⭐⭐⭐⭐ |
| 箭头函数(多语句) | const add = (a, b) => { const sum = a + b; return sum; } |
匿名 | ⭐ | ⭐ | ⭐⭐ |
| 箭头函数(返回对象) | const createObj = (name, age) => ({ name, age }); |
匿名 | ⭐ | ⭐ | ⭐⭐ |
汇总表
| 写法 | 适用场景 | ES 版本 | 函数提升 | 自有 this |
|---|---|---|---|---|
| 函数声明 | 全局通用函数、工具函数 | ES3 | ✅ | ✅ |
| 函数表达式 | 条件定义、回调传递 | ES3 | ❌ | ✅ |
| 箭头函数 | 简短回调、需要绑定外层 this | ES6+ | ❌ | ❌ |
| Function 构造函数 | 动态字符串生成函数 | ES3 | ❌ | ✅ |
一句话总结
- 对象内部:优选方法简写
greet() {},需要递归或调试时用具名函数表达式。 - 对象外部:全局通用函数用函数声明,回调传参用箭头函数,需要动态定义时用函数表达式。