函数是一等公民

理解 JavaScript 中函数作为一等公民的含义和应用

问题

谈谈你对函数是一等公民的理解。

解答

“一等公民”(First-class Citizen)意味着函数和其他数据类型(如数字、字符串)享有同等地位。具体表现为:

1. 函数可以赋值给变量

// 函数表达式赋值给变量
const greet = function(name) {
  return `Hello, ${name}!`;
};

console.log(greet('World')); // Hello, World!

2. 函数可以作为参数传递

// 回调函数作为参数
function execute(fn, value) {
  return fn(value);
}

const double = x => x * 2;
const square = x => x * x;

console.log(execute(double, 5)); // 10
console.log(execute(square, 5)); // 25

3. 函数可以作为返回值

// 高阶函数:返回一个函数
function createMultiplier(factor) {
  return function(number) {
    return number * factor;
  };
}

const triple = createMultiplier(3);
const quadruple = createMultiplier(4);

console.log(triple(10));    // 30
console.log(quadruple(10)); // 40

4. 函数可以存储在数据结构中

// 函数存储在数组中
const operations = [
  x => x + 1,
  x => x * 2,
  x => x ** 2
];

let result = 3;
operations.forEach(fn => {
  result = fn(result);
});
console.log(result); // 64  (3+1=4, 4*2=8, 8^2=64)

// 函数存储在对象中
const calculator = {
  add: (a, b) => a + b,
  subtract: (a, b) => a - b,
  multiply: (a, b) => a * b
};

console.log(calculator.add(2, 3)); // 5

5. 函数可以拥有属性

// 函数本质是对象,可以添加属性
function counter() {
  counter.count++;
  return counter.count;
}

counter.count = 0;
counter.reset = function() {
  counter.count = 0;
};

console.log(counter()); // 1
console.log(counter()); // 2
counter.reset();
console.log(counter()); // 1

实际应用:函数组合

// 利用一等公民特性实现函数组合
const compose = (...fns) => x => 
  fns.reduceRight((acc, fn) => fn(acc), x);

const addOne = x => x + 1;
const double = x => x * 2;
const square = x => x * x;

// 从右到左执行:square -> double -> addOne
const compute = compose(addOne, double, square);

console.log(compute(3)); // 19  (3^2=9, 9*2=18, 18+1=19)

关键点

  • 赋值:函数可以像普通值一样赋给变量
  • 传参:函数可以作为参数传递给其他函数(回调函数)
  • 返回值:函数可以作为另一个函数的返回值(闭包、高阶函数)
  • 存储:函数可以存储在数组、对象等数据结构中
  • 属性:函数本身是对象,可以拥有自己的属性和方法