在 JavaScript 中,函数是第一类对象,这意味着它们可以像其他对象一样被创建、传递和操作。下面我将介绍函数对象和命名函数表达式 (Named Function Expression, NFE) 的相关知识。
在 JavaScript 中,函数是 Function
类型的实例,具有属性和方法。
函数声明:
function sayHello() {
console.log("Hello!");
}
函数表达式:
const sayHello = function() {
console.log("Hello!");
};
箭头函数 (ES6+):
const sayHello = () => console.log("Hello!");
函数对象有一些有用的属性:
name
: 函数名称length
: 函数期望的参数个数prototype
: 函数的原型对象function sum(a, b) {
return a + b;
}
console.log(sum.name); // "sum"
console.log(sum.length); // 2
命名函数表达式是指函数表达式中的函数有一个名称。
const factorial = function innerFact(n) {
return n <= 1 ? 1 : n * innerFact(n - 1);
};
这里 innerFact
就是函数的名称,这种形式有几个特点:
可以在函数内部引用自身:
const factorial = function innerFact(n) {
if (n <= 1) return 1;
return n * innerFact(n - 1); // 使用函数名递归调用
};
调试时堆栈跟踪更清晰:
(anonymous function)
函数名在函数内部是常量:
NFE 的函数名只在函数内部可见:
const foo = function bar() {
console.log(typeof bar); // "function" - 在函数内部可用
};
console.log(typeof bar); // "undefined" - 在外部不可见
NFE 和函数声明不同:
// 函数声明
function foo() {}
// 命名函数表达式
const bar = function baz() {};
函数声明会提升(hoisting),而 NFE 不会。
// 使用 NFE 实现递归
const fibonacci = function fib(n) {
if (n <= 1) return n;
return fib(n - 1) + fib(n - 2);
};
console.log(fibonacci(10)); // 55
// 即使变量被重新赋值,函数名仍然有效
const original = fibonacci;
fibonacci = null;
console.log(original(10)); // 仍然可以工作,因为内部使用 fib 名称
总结来说,命名函数表达式(NFE)在需要递归调用或更好的调试体验时非常有用,它提供了函数内部的自我引用能力,同时保持了函数名的局部作用域。