在本教程中,您将了解 JavaScript 一等公民,也就是函数。这意味着您可以将函数存储在变量中,将它们作为参数传递给其他函数,并将它们作为值从其他函数返回。

在变量存储函数

函数是 JavaScript 的一等公民。换句话说,您可以像对待其他类型的值一样对待函数。

下面定义 add() 函数并将函数名称分配给变量 sum

function add(a, b) {
    return a + b;
}

let sum = add;

在赋值语句中,我们不在函数名末尾包含左括号和右括号。因为我们不执行 add 函数,而是引用 add 函数。

通过这样做,我们可以有两种方法来执行相同的函数。比如我们可以正常调用 add 函数,如下:

let result = add(10, 20);

或者,我们也可以像这样通过 sum 变量调用 add() 函数:

let result = sum(10,20);

将函数传递给另一个函数

因为函数是值,所以您可以将一个函数作为参数传递给另一个函数。

下面声明 average() 接受三个参数的函数。第三个参数是一个函数:

function average(a, b, fn) {
    return fn(a, b) / 2;
}

现在,您可以按如下方式将 sum 函数传递给 average() 函数:

let result = average(10, 20, sum);

把它们放在一起:

function add(a, b) {
    return a + b;
}

let sum = add;

function average(a, b, fn) {
    return fn(a, b) / 2;
}

let result = average(10, 20, sum);

console.log(result);

输出:

15

函数返回函数

由于函数是值,您可以从另一个函数返回一个函数。

以下 compareBy() 函数返回一个函数,返回的函数用于两个对象的属性比较:

function compareBy(propertyName) {
  return function (a, b) {
    let x = a[propertyName],
      y = b[propertyName];

    if (x > y) {
      return 1;
    } else if (x < y) {
      return -1;
    } else {
      return 0;
    }
  };
}

请注意,a[propertyName] 返回 a 对象 propertyName 的值。它等同于 a.propertyName。

但是,如果 propertyName 包含像 'Discount Price' 这样的空格,则需要使用方括号表示法来访问它。

假设您有一个产品对象数组,其中每个产品对象都有两个属性: nameprice

let products = [
    {name: 'iPhone', price: 900},
    {name: 'Samsung Galaxy', price: 850},
    {name: 'Sony Xperia', price: 700}
];

您可以通过调用 sort() 方法对数组进行排序sort() 方法接受一个函数作为参数,用于比较数组的两个元素。

例如,你可以排序产品基于对象属性的名称 name,通过 compareBy() 传递 sort 函数,如下所示 。

console.log('Products sorted by name:');
products.sort(compareBy('name'));

console.table(products);

输出:

Products sorted by name:
┌─────────┬──────────────────┬───────┐
│ (index) │       name       │ price │
├─────────┼──────────────────┼───────┤
│    0    │ 'Samsung Galaxy' │  850  │
│    1    │  'Sony Xperia'   │  700  │
│    2    │     'iPhone'     │  900  │
└─────────┴──────────────────┴───────┘

同样,您可以按价格对产品对象进行排序:

// 通过产品价格排序产品

console.log('通过产品价格排序产品');
products.sort(compareBy('price'));
console.table(products);

输出:

通过产品价格排序产品:
┌─────────┬──────────────────┬───────┐
│ (index) │       name       │ price │
├─────────┼──────────────────┼───────┤
│    0    │  'Sony Xperia'   │  700  │
│    1    │ 'Samsung Galaxy' │  850  │
│    2    │     'iPhone'     │  900  │
└─────────┴──────────────────┴───────┘

把它们放在一起。

function compareBy(propertyName) {
  return function (a, b) {
    let x = a[propertyName],
      y = b[propertyName];

    if (x > y) {
      return 1;
    } else if (x < y) {
      return -1;
    } else {
      return 0;
    }
  };
}
let products = [
  { name: 'iPhone', price: 900 },
  { name: 'Samsung Galaxy', price: 850 },
  { name: 'Sony Xperia', price: 700 },
];

// 通过产品名称排序产品
console.log('Products sorted by name:');
products.sort(compareBy('name'));

console.table(products);

// 通过产品价格排序产品
console.log('Products sorted by price:');
products.sort(compareBy('price'));
console.table(products);

JavaScript 函数是一等公民示例

以下示例定义了两个函数,将以厘米为单位的长度转换为英寸,反之亦然:

function cmToIn(length) {
    return length / 2.54;
}

function inToCm(length) {
    return length * 2.54;
}

下面的 convert() 函数有两个参数。第一个参数是一个函数,第二个参数是长度。

function convert(fn, length) {
    return fn(length);
}

要将 cm 转换为 in,可以调用 convert() 函数并将 cmToIn 函数作为第一个参数传递给 convert() 函数:

let inches = convert(cmToIn, 10);
console.log(inches);

输出:

3.937007874015748

同样,要将长度从英寸转换为厘米,您可以将 inToCm 函数传递给 convert() 函数,如下所示:

let cm = convert(inToCm, 10);
console.log(cm);

输出:

25.4

把它们放在一起。

function cmToIn(length) {
  return length / 2.54;
}

function inToCm(length) {
  return length * 2.54;
}

function convert(fn, length) {
  return fn(length);
}

let inches = convert(cmToIn, 10);
console.log(inches);

let cm = convert(inToCm, 10);
console.log(cm);

输出:

3.937007874015748
25.4

结论

  • 函数是 JavaScript 的一等公民,你也可以称这种编程方式为高阶函数。
  • 您可以将函数作为参数传递给其他函数,将它们作为值从其他函数返回,并将函数存储在变量。