JOVANA
Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

函数:可复用的小机器

把一件活儿写一次、给它起个名字,然后一遍又一遍地使用它——这就是函数,编程里最有用的那一个概念。

核心想法:一台你能命名的机器

想象你桌上放着一台小小的自动售货机。你投进几枚硬币、按下一个按钮,零食就掉出来了。你不会每次饿了都重造一台机器——你只是再用它一次。函数就是这样一台机器,只不过是用代码做的:你给它一些输入,它干一件活儿,再把一个结果递还给你。

这里的关键词是复用。你把机器造出来一次,给它起个清楚的名字,比如 add、greet 或 sendEmail——从此以后,你想运行它多少次都行,从程序的任何地方,只要叫出它的名字就可以。写一次,处处用。

解剖:函数的四个部件

每个函数都由同样的四个部件搭成,一旦你能认出它们,就能读懂任何语言里的任何函数。它们是:名字(以后你用什么来叫它)、参数(输入塞进去的那些槽位)、函数体(它实际干的活儿),以及返回值(它递还给你的结果)。这里有一个完整的小例子:

function greet(name) {
  return "Hello, " + name + "!";
}

greet("Mia");   // -> "Hello, Mia!"
名字:greet。参数:name。函数体:那行拼出问候语的代码。返回值:拼好的那句问候。

把它当成一句话来读。function 这个词在宣告:「我要造一台机器了。」greet 是机器外壳上写的名字。括号里的 (name) 是输入的槽位。大括号里的一切是函数体——也就是那件活儿。而 return 就是机器把结果放进你手心的那一刻。整个结构就这么简单。

为什么它们重要:写一次,改一次

设想一个程序,它在十二个不同的地方向用户打招呼,每一次你都把同样那三行拼问候语的代码复制粘贴了一遍。这种复制粘贴出来的填充物有个名字:样板代码(boilerplate),就是那些反复出现、把代码塞得乱糟糟、却不带来任何新意的「管道工程」。十二份副本,意味着十二次打错字的机会,和十二个要记着的地方。

现在设想同一个程序,只有一个 greet 函数,被调用了十二次。逻辑只存在于唯一的一个地方。等哪天你决定问候语该说「Welcome」而不是「Hello」,你只改这一处——那十二个调用它的地方就全都免费跟着更新了。这就是函数那个安静的超能力:只在一个地方修 bug

这也是为什么函数让重构(refactor)——也就是在不改变功能的前提下整理、重塑你的代码——变得轻松得多。当每一件活儿都封装在它自己那台有名字的机器里时,你就可以给它改名、让它跑得更快、或者替换它的内部,全程都不必碰程序的其他部分。整齐的盒子,最好挪动。

调用 vs 定义:先造出来,再按按钮

一个函数的「一生」里有两个截然不同的时刻,新手常把它们混为一谈。定义一个函数,是在造机器——把名字、槽位、函数体都写出来。这时候其实什么都还没发生;你只是把它装配好,搁到架子上。调用一个函数,是按下它的按钮——告诉它「上,现在就去干活,输入在这里」。

当你调用它时,你递过去的值会填进那些参数槽位。在函数内部,这些输入就像一批崭新的变量(variables)——一个个有名字的盒子,机器在运行时可以读取它们、用它们干活。传进 "Mia",那个叫 name 的盒子在这一趟活儿里就装着 "Mia"。再用 "Sam" 调用一次,同一台机器这回就改用 "Sam" 来干活了。

function add(a, b) {   // define it once
  return a + b;
}

add(2, 3);   // call it -> 5
add(10, 7);  // call it again -> 17
定义一次,调用两次。每次调用都用不同的输入填进 a 和 b 这两个槽位,并各自得到自己的结果。

小结:要带走的那一个想法

函数是你作为程序员将拉动的第一根真正的杠杆,你日后造的几乎一切,都是由它们搭起来的。整个想法一口气就能说完:给一件活儿起个名字、喂给它输入、拿到结果、然后永远复用它。掌握了这一点,你的代码就不再是一长条往下拉的卷轴,而开始变成一间作坊,里头摆满了整齐、贴好标签的小机器。

  1. 定义一次:写出名字、参数槽位、函数体,以及一个返回值。
  2. 想调用多少次就多少次:说出名字,括号里放上真实的输入。
  3. 把输入传进去:它们会填进参数,在函数内部就像崭新的变量一样。
  4. 双重收获:现在少写重复的样板代码,以后修改或重构只需动一处。