简介
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开发生涯有多重要。我建议你在代码中练习各种使用函数的方法!