学习JavaScript中的第一类函数

41 阅读2分钟

简介

JavaScript有第一类函数。这意味着函数可以像其他值一样被处理,这在你成为一名JavaScript开发者的过程中是非常重要的行为。下面三个小标题代表了重要的一级函数行为。

  • 函数可以被分配给变量
  • 函数可以作为参数传递给其他函数
  • 函数可以从其他函数中返回

让我们用基本的例子来探讨这些项目,然后在最后用几个更复杂的、真实世界的例子把它们集中起来

将函数分配给变量

让我们创建一个返回文本"Hello" 的函数,然后将该函数分配给一个变量,创造性地命名为sayHello

const sayHello = () => {
  return 'Hello';
};

console.log(sayHello());
// "Hello"

相当基本啊!让我们继续前进。

将一个函数作为一个参数传递

让我们把前面提到的sayHello 函数作为一个参数传递给另一个函数。这个另一个函数将向一个特定的人问好。

const sayHelloToPerson = (greeter, person) => {
  return greeter() + ' ' + person;
};

console.log(sayHelloToPerson(sayHello, 'John'));
// Hello John

简单说明一下当我们把sayHello 函数传递给sayHelloToPerson 时发生了什么:在sayHelloToPerson 函数中,变量greeter 现在将指向内存中的sayHello 函数。当我们调用greeter() 时,该函数就被调用了!

注意:在这种情况下,我通常会使用模板字面(即:return `${greeter()} ${person}` ),但在这个例子中,我不想让模板字面的语法把水弄得太浑。

从另一个函数中返回一个函数

也许我们并不总是想说"Hello" ,而是想选择创建任意数量的不同类型的问候语。让我们使用一个函数,让我们创建问候语的函数。

const greeterMaker = (greeting) => {
  return (person) => {
    return greeting + ' ' + person;
  };
};

const sayHelloToPerson = greeterMaker('Hello');
const sayHowdyToPerson = greeterMaker('Howdy');

console.log(sayHelloToPerson('Joanne'));
// "Hello Joanne"

console.log(sayHowdyToPerson('Joanne'));
// "Howdy Joanne"

我们的greeterMaker ,是一个可以创建函数的函数!很有趣,对吗?

一些有趣的、现实世界的使用案例

现在我们已经了解了一流函数的基础知识,让我们来看看一些真实世界的用例吧

对象验证

也许你有一堆标准,一个对象(例如,新的用户信息)需要通过才能被视为 "有效"。让我们创建一个函数,迭代所有的标准,并返回对象是否有效。

const usernameLongEnough = (obj) => {
  return obj.username.length >= 5;
};

const passwordsMatch = (obj) => {
  return obj.password === obj.confirmPassword;
};

const objectIsValid = (obj, ...funcs) => {
  for (let i = 0; i < funcs.length; i++) {
    if (funcs[i](obj) === false) {
      return false;
    }
  }

  return true;
};

const obj1 = {
  username: 'abc123',
  password: 'foobar',
  confirmPassword: 'foobar',
};

const obj1Valid = objectIsValid(obj1, usernameLongEnough, passwordsMatch);
console.log(obj1Valid);
// true

const obj2 = {
  username: 'joe555',
  password: 'foobar',
  confirmPassword: 'oops',
};

const obj2Valid = objectIsValid(obj2, usernameLongEnough, passwordsMatch);
console.log(obj2Valid);
// false

如果你对JavaScript比较陌生,你可能需要读几遍才能明白发生了什么,但相信我,一旦你明白了,回报是巨大的

注意:如果你不熟悉rest operator (...),这只是让所有提供给函数的剩余参数按指定的名称放入一个数组。

API密钥闭合

也许我们有一种情况,我们想用一个API密钥连接到一个API。我们可以在每个请求中添加这个密钥,或者,我们可以创建一个函数,接受一个API密钥参数,并在每个请求中返回包含API密钥的函数。

重要的是。不要把秘密的API密钥放在前端代码中。相反,想象一下下面的代码是在一个基于节点的后端。

const apiConnect = (apiKey) => {
  const getData = (route) => {
    return axios.get(`${route}?key=${apiKey}`);
  };

  const postData = (route, params) => {
    return axios.post(route, {
      body: JSON.stringify(params),
      headers: {
        Authorization: `Bearer ${apiKey}`,
      },
    });
  };

  return { getData, postData };
};

const api = apiConnect('my-secret-key');

// No need to include the apiKey anymore
api.getData('http://www.example.com/get-endpoint');
api.postData('http://www.example.com/post-endpoint', { name: 'Joe' });

结论

就这样,你拥有了它!希望你现在已经看到了JavaScript中的函数是真正一流的,以及函数对你的JavaScript开发生涯有多重要。我建议你在代码中练习各种使用函数的方法!