本文是JavaScript基础教程中的第三章,在这一章中,我们将学习如何使用函数来简化和重用代码。
什么是函数?
让我们想象一下:你有一个机器人,它可以听懂你的命令,并按照你的要求做事情。
比如,你可以对它说:
- “向前走三步”
- “向右转90度”
- “拿起桌子上的苹果”
- “放到篮子里”
这些都是简单的命令,机器人可以很容易地执行。但是,如果你想让机器人做一些更复杂的事情,比如:
- “把桌子上的所有水果都放到篮子里”
这时候,你就不能只用一句话来指示机器人了,因为桌子上可能有不同的水果,并且不同水果的位置也不同。你需要给它一系列的命令,比如:
- “向前走三步”
- “拿起桌子上的苹果”
- “放到篮子里”
- “向左转90度”
- “向前走两步”
- “拿起桌子上的香蕉”
- “放到篮子里”
- “向左转90度”
- “向前走两步”
- “拿起桌子上的橘子”
- “放到篮子里”
但这样做的话,你不仅会需要说一大堆话,还可能会忘记或者说错某些命令,导致机器人出错。而这还不是主要的,主要的是,当你每次想让机器人做这件事情时, 都要重复说一遍这一堆话,效率低下、极不优雅。
有没有更好的办法呢?当然有!你可以把这些命令分组成一个可重复使用的单元,并给它一个名字,比如“收拾水果”。然后,当你想让机器人做这件事情时,你只需要对它说:
- “收拾水果”
机器人就会按照之前设定好的命令序列去执行啦~
在编程中,我们也可以使用类似的方法来简化和重用代码。我们可以把一组有名字的命令叫做函数(function)。 函数就像是一个小程序,它可以完成一个特定的任务。我们可以在代码中定义一个函数,并给它一个名字。然后,我们可以在其他地方调用这个函数,让它执行我们设定好的操作。
与数学函数的区别
数学的函数是一种抽象的映射关系,它是数学理论的基础和工具,用来描述自然界和人类社会中的各种规律和现象。 而编程的函数是一种具体的解决问题的方法,用来实现各种功能和需求。
二者的联系主要在于它们都是一种映射关系。为了避免将二者混淆,也许你可以暂时把编程中的 function 理解为「功能」或者「方法」。
拓展阅读
数学家和计算机科学家对函数的看法和使用方法是不同的。数学家更关注函数的性质、结构、变化、分类等,他们会用严格的逻辑推理来证明或推导函数的各种定理和公式。 计算机科学家更关注函数的效率、可读性、可复用性、可扩展性等,他们会用不同的编程语言和编程范式来设计或实现函数的各种算法和程序。
数学中有一种特殊的函数叫做 lambda演算 ,它是一种基于函数抽象和应用的形式系统,可以用来表示任何可计算的函数。 lambda演算中的函数可以用lambda表达式来表示,它是一种匿名的、简单的、高阶的函数,它可以作为参数传递给其他函数,也可以作为返回值返回给其他函数。
lambda表达式的一般形式是:,其中x是变量,M是函数体。
而lambda表达式也是 函数式编程 的核心概念之一,函数式编程是一种编程范式,它强调数学函数的概念,将程序看作是输入和输出之间的映射关系, 不改变原始输入数据,也不产生副作用。因此,函数式编程中的函数与数学中的函数更加相似。
但要注意,并不是所有的编程语言都支持或适合函数式编程,有些编程语言更倾向于命令式编程或面向对象编程 ,这些编程范式有不同的优缺点和适用场景。
如何定义和调用函数?
在 JavaScript 中,我们可以使用 function
关键字来定义一个函数,然后给它一个名字和一对圆括号。
在圆括号里面,我们可以写一些参数(parameter),它们是函数需要的输入信息。
在花括号里面( { ... }
),我们可以写一些命令(statement),它们是函数要执行的操作。比如,我们可以这样定义一个叫做 sayHello
的函数:
function sayHello() {
alert("Hello, welcome to JavaScript!");
alert("How are you today?");
}
它只有两个命令,就是弹出对话框显示欢迎语与问候语。
要调用一个函数,我们只需要写上它的名字和一对圆括号即可。比如,我们可以这样调用 sayHello
函数:
sayHello();
这样就会弹出一个对话框显示“Hello, welcome to JavaScript!”,接着又会弹出一个对话框显示“How are you today?”。
带参数的函数
有时候,我们希望函数能够给根据我们的不同的数据返回一些输出信息,比如计算结果或者处理后的数据。
这时候我们就只需要定义一个函数,然后传递不同的参数(parameter)给它,接着使用 return
关键字来指定函数要返回的值。
比如,我们可以定义一个叫做 add
的函数,它可以接受两个参数(两个数),然后返回它们的和:
function add(a, b) {
return a + b;
}
这个函数有两个参数 a
和 b
,它们表示要相加的两个数。它有一个 return
语句,表示要返回 a
和 b
的和。
要调用这个函数,并获取返回值,我们可以把它赋值给一个变量,或者直接用在其他表达式中。
比如,我们可以这样调用 add
函数,并把它的返回值赋值给一个叫做 sum
的变量:
var sum = add(3, 5);
这样 sum
的值就是 8 了。
或者我们可以直接把 add
函数用在其他表达式中,比如:
alert(add(3, 5) * 2);
这样就会弹出一个对话框显示 16 ,因为 add(3, 5)
的值是 8 ,然后乘以 2 。
可见,使用参数后,我们只需要定义一个add函数,而不需要为每一对数都定义一个不同的函数
(比如 addFiveAndFive
,addFiveAndSix
,addSixAndSix
...)。
实际参数与形式参数
在上面我们传给 add
函数的只是一些常数数值,如果我们给它传入的是变量,会怎么样呢?
在JavaScript中,参数是按值传递的,也就是说,函数内部的参数是函数外部传递进来的实参(比如变量)的副本,而不是实参本身。
因此,修改形式参数(函数内部的参数)并不会影响到实际参数(函数外部传递进来的参数)。比如:
// 定义一个带一个参数的函数
function change(x) {
// 修改参数的值
x = x + 1;
}
// 定义一个变量,并赋值为 10
var y = 10;
// 调用函数,并传递变量 y 作为实参
change(y);
// 打印变量 y 的值
console.log(y); // y 的值还是 10,并没有被改变
但是,如果参数是一个可变类型的值,比如数组或者对象,那么在函数内部修改参数的属性或者元素,就会影响到外部传递进来的实参。 关于这部分内容,我们会在JavaScript基础教程:数组与重构与JavaScript基础教程:对象与面向对象编程中详细介绍。
默认参数
在JavaScript中,参数可以有默认值。如果在调用函数时没有传递某个参数,那么这个参数就会使用定义时指定的默认值。比如:
// 定义一个带两个参数的函数,并给第二个参数指定默认值为 1
function multiply(a, b = 1) {
// 返回两个参数的乘积
return a * b;
}
// 调用函数,并只传递一个实参
var result = multiply(5); // result 的值是 5 * 1 = 5
// 调用函数,并传递两个实参
var result = multiply(5, 2); // result 的值是 5 * 2 = 10
通过这个特性,我们可以简化函数的调用,避免传递参数时出错。
剩余参数
默认参数特性是针对于传入参数不够的情况,而对于传入参数过多的情况,我们可以使用剩余参数(rest parameter)。
在JavaScript中,使用剩余参数(rest parameter)可以装入所有剩余的参数。比如:
// 定义一个带剩余参数的函数
function print(a, ...rest) {
// 打印第一个参数
console.log(a);
// 打印剩余参数
console.log(rest);
}
// 调用函数,并传递多个实参
print(2, 1, 2, 3);
这样,我们会得到打印结果:
2
[1, 2, 3]
可以看到, 2
是作为第一个参数传递给 print
函数的,而 1
,2
,3
则是作为剩余参数传递给 print
函数的,
它们最后被一起打包装进了 [1, 2, 3]
中。
我们把 [1, 2, 3]
这样形式的数据称为数组,它就像一个盒子,可以装很多东西,而且可以通过下标来访问里面的元素。
更多内容我们会在
JavaScript基础教程:数组 中介绍。现在你只需要知道,JavaScript会把剩余参数都装进一个盒子,即数组中,
然后把这个数组赋值给我们命名的 rest
变量,所以 rest
的值就是 [1, 2, 3]
。需要注意的是,...
是必须的,
否则JavaScript可不知道你想把多的参数都装进 rest
中!
如何使用内置的函数和自定义的函数?
在 JavaScript 中,除了我们自己定义的函数外,还有很多内置的函数(built-in function),它们是由 JavaScript 提供的,
可以直接使用。比如,我们之前用过的 alert
就是一个内置的函数,它可以弹出一个对话框显示信息。还有很多其他的内置函数,比如:
console.log
可以在控制台(console)输出信息document.write
可以在网页上输出信息prompt
可以弹出一个对话框让用户输入信息Math.random
可以生成一个随机数Date.now
可以获取当前的时间戳
内置对象
你可以在 MDN 的 JavaScript 标准内置对象 页面查看更多的内置对象和函数。
使用内置的函数和自定义的函数的方法是一样的,都是写上函数名和圆括号,并根据需要传递参数或者获取返回值。比如,我们可以这样使用一些内置的函数:
console.log("Hello, console!"); // 在控制台输出 Hello, console!
document.write("Hello, document!"); // 在网页上输出 Hello, document!
var name = prompt("What is your name?"); // 弹出一个对话框让用户输入名字,并把输入赋值给 name 变量
var number = Math.random() * 10; // 生成一个 0 到 10 之间的随机数,并赋值给 number 变量
var time = Date.now(); // 获取当前的时间戳,并赋值给 time 变量
时间戳
时间戳是一种用来表示时间的数字,它通常是从1970年1月1日0点0分0秒(UTC)开始计算的秒数或毫秒数。 它有很多用途,比如在编程中可以用来记录事件发生的时间,或者在网络中可以用来同步不同设备的时间。
创建一些有趣的网页效果...?
使用函数,我们可以实现一些有趣的网页效果,让我们的网页更加生动和有趣。
但在使用函数实现这些效果之前,我们的编程学习任重而道远,至少我们还需要掌握条件(condition),循环(loop)的用法! 但别担心,绝对不会很难,我们将在之后再进行有趣的网页效果制作!
总结
本章是JavaScript基础教程系列的第三章,介绍了JavaScript的基本语法和一些常用的内置函数。
函数是一组有名字的命令,可以有参数和返回值,它用来完成一个特定的任务,简化和重用代码。
在JavaScript中,我们使用function关键字来定义函数,然后通过函数名加圆括号来调用函数。
在定义函数时,在圆括号内部写入参数,调用函数时在圆括号内部传递参数;使用return关键字来指定函数的返回值。
在定义函数时,我们可以给参数指定默认值,这样在调用函数时,如果没有传递参数,就会使用默认值。
我们还可以使用剩余参数(rest parameter)来装入所有剩余的参数,这样就可以接受任意数量的参数。
JavaScript中有很多内置的函数,比如alert、prompt、Math.random等,它们可以直接使用。
小试牛刀
线上沙盒
本章的练习都可以在控制台中完成,当然你可以尝试一下在线上沙盒: CodePen 上完成😊
CodePen的基本使用非常简单,以我们上一章的Hello World练习题为例:
在HTML窗口中写入 <body>
标签中的内容,然后在JS窗口中写入JS代码,CodePen就会自动执行你的代码,并将网页效果呈现在下方的窗口中。
函数参数
你对函数参数是如何理解的?它们有什么作用?
温度转换
请写一个函数,它可以接受一个数字参数作为华氏温度,然后返回它对应的摄氏温度,你需要将结果打印在页面上或控制台中。
生成随机颜色
请写一个函数,它可以生成一个随机的颜色,并返回这个颜色。
提示
颜色是由红、绿、蓝三种颜色的不同比例混合而成的,
每种颜色的取值范围是0到255,比如红色可以表示为 rgb(255, 0, 0)
,
绿色可以表示为 rgb(0, 255, 0)
,蓝色可以表示为 rgb(0, 0, 255)
。