Menu Close

JavaScript 函数 Functions, 变量,常量,全局变量和局部变量

摘要:本教程将介绍 JavaScript 函数的基础知识,以及如何使用函数将代码结构化为更小且可重用的单元。

在脚本的许多地方,我们经常需要执行类似的操作。

在开发应用程序时,您经常需要在多个地方执行相同的操作。为了避免重复编写相同的代码,可以使用函数将其封装并重用。

JavaScript 提供了许多内置函数,如 parseInt() , parseFloat(), alert(message)、prompt(message, default) 和 confirm(question)。本教程将指导您如何开发自定义函数。

例如,当访客登录、登出,或在其他场景中,我们可能都需要显示一条漂亮的消息。

函数是程序的主要“构建块”。它们允许我们多次调用相同的代码,而无需重复书写。JavaScript 中的函数是可以定义并在需要时调用的代码片段。它们可以被看作是程序中的子程序。

函数非常有用,因为它们允许程序员只编写一次代码,然后在程序中多次重复使用,从而减少代码重复。同时,函数也使程序员能够创建逻辑上独立的代码段,这些代码段可以与程序中的其他部分区分开来。如果需要更详细的了解函数,可参考C语言的函数介绍

函数具有以下特点:

  • 可以接受零个或多个参数

  • 可以在函数调用结束时返回一个指定的值

  • 即使不返回值,也可以对程序的其他部分产生副作用

JavaScript 函数 Functions
JavaScript 函数 Functions

函数声明

要声明一个函数,使用 function 关键字,后跟函数名、参数列表和函数体,如下所示:

例如:


function 关键字写在最前面,然后是函数的名称,接着是括号中的参数列表(用逗号分隔,上面的例子中是空的,稍后我们会看到带参数的例子),最后是函数的代码,也称为“函数体”,包裹在花括号中。

我们可以通过函数名 showMessage() 来调用新函数。

例如:

调用 showMessage() 会执行该函数的代码。在这个例子中,我们会看到这条消息出现两次。

函数名必须是有效的 JavaScript 标识符。按照惯例,函数名采用驼峰命名法,并以动词开头,例如 getData()fetchContents()isValid()

函数可以接受零个、一个或多个参数。多个参数之间用逗号分隔。

这个例子清楚地展示了函数的主要用途之一:避免代码重复。

如果我们需要更改消息的内容或显示方式,只需修改一个地方:输出消息的那个函数。

在函数体内,您可以编写实现特定操作的代码。例如:

上述 say() 函数将消息输出到控制台。

调用函数

要使用函数,需要调用它。调用函数也称为执行函数。

调用函数的语法如下:

示例:

在此示例中,我们调用了 say() 函数,并传入了字符串 'Hello' 作为参数。

参数与实参

术语“参数”和“实参”经常互换使用,但它们本质上是不同的。

  • 参数(Parameter):在声明函数时指定的变量。

  • 实参(Argument):在调用函数时传递给函数的实际值。

例如,在 say() 函数中,message 是参数,而 'Hello' 是对应于 message 参数的实参。

返回值

JavaScript 中,每个函数默认返回 undefined,除非您显式指定返回值。

示例:

输出:

要为函数指定返回值,使用 return 语句,后跟表达式或值:

输出:

函数可以根据条件返回不同的值:

此外,您可以使用 return 语句提前退出函数:

arguments 对象

在函数内部,可以访问一个名为 arguments 的对象,它表示传递给函数的所有实参。

arguments 对象类似于数组,但不是数组的实例。您可以使用索引访问各个参数:

函数提升(Hoisting)

JavaScript 中,您可以在声明函数之前调用它。这是因为函数声明会被提升到代码的顶部。

示例:

函数提升使得您可以在函数声明之前调用函数,从而使开发流程更加顺畅。

总结

  • 使用 function 关键字声明函数。
  • 使用 functionName() 调用函数。
  • 如果函数没有显式返回值,则默认返回 undefined
  • 使用 return 语句显式返回值。
  • arguments 对象是函数内部的类数组对象,表示传递给函数的实参。
  • 函数提升允许您在声明函数之前调用它。

局部变量

在函数内部声明的变量只能在该函数内部访问。

例如:

外部变量

函数也可以访问外部的变量,例如:

函数可以完全访问外部变量,也可以修改它。

例如:

只有在函数内部没有声明同名的局部变量时,外部变量才会被使用。

如果在函数内部声明了一个同名的变量,它会遮蔽(shadow)外部的变量。例如,在下面的代码中,函数使用的是局部的 userName,外部的 userName 被忽略了:

全局变量

在任何函数外部声明的变量,比如上面代码中的外部 userName,称为全局变量。

全局变量可以在任何函数中访问(除非被局部变量遮蔽)。

最好尽量减少使用全局变量。现代代码中全局变量较少或没有。大多数变量都驻留在它们各自的函数中。不过,有时全局变量可以用来存储项目级别的数据。

参数

我们可以通过参数将任意数据传递给函数。

在下面的例子中,函数有两个参数:fromtext

当函数在 (*) 和 (**) 行被调用时,传入的值会被复制到局部变量 fromtext 中。然后,函数使用这些局部变量。

这是另一个例子:我们有一个变量 from 并将其传递给函数。请注意:函数可以修改 from,但外部并不会看到这个变化,因为函数总是接收到值的副本:

当一个值作为函数参数传递时,它也被称为实参。

换句话说,澄清这些术语的定义:

  • 参数 是在函数声明时括号内列出的变量(这是声明时的术语)。

  • 实参 是在调用函数时传递给函数的值(这是调用时的术语)。

我们声明函数时列出其参数,然后在调用时传递实参。

在上面的例子中,可以这样说:“showMessage 函数声明时有两个参数,然后在调用时传入了两个实参:from"Hello"。”

默认值

如果调用了一个函数,但未提供某个参数,则对应的值将变为 undefined。

例如,上述函数 showMessage(from, text) 可以只用一个参数进行调用:

这不是错误。这样的调用会输出 “Ann: undefined”。由于未传入 text 的值,它变为 undefined。

我们可以在函数声明中使用 = 为参数指定所谓的“默认”(在省略时使用)值:

现在如果未传入 text 参数,它将获得值 “no text given”。

如果参数存在但严格等于 undefined,默认值也会生效,如下所示:


这里的 “no text given” 是一个字符串,但它也可以是更复杂的表达式,且仅在参数缺失时才会被计算并赋值。因此,这也是可行的:

默认参数的求值

JavaScript 中,每次调用函数且未提供相应参数时,默认参数都会被求值。

在上面的例子中,如果提供了 text 参数,anotherFunction() 根本不会被调用。

另一方面,每次缺少 text 参数时,它都会被单独调用一次。

默认参数的替代

有时在函数声明之后的某个阶段为参数赋默认值更有意义。

我们可以在函数执行期间通过将参数与 undefined 进行比较来检查是否传入了该参数:


……或者我们可以使用 || 运算符


现代 JavaScript 引擎支持空值合并运算符 ??,当大多数假值(如 0)应被视为“正常”时,它更合适:

返回值

函数可以将一个值作为结果返回到调用代码中。

最简单的例子是一个将两个值相加的函数:

指令 return 可以出现在函数的任意位置。当执行到它时,函数将停止,并将该值返回给调用代码(在上面的例子中赋值给 result)。

一个函数中可能会有多处 return。例如:

下面的示例在一个函数中使用多个 return 语句来根据条件返回不同的值:


compare()函数比较两个值。它返回:

  • 如果第一个参数大于第二个参数,则返回 -1 。
  • 如果第一个参数小于第二个参数,则返回 1。
  • 如果第一个参数等于第二个参数,则返回 0。

函数在到达 return 语句时立即停止执行。因此,您可以使用不带值的 return 语句来提前退出函数,如下所示:

例如:


在上面的代码中,如果 checkAge(age) 返回 false,那么 showMovie 将不会继续执行 alert。

JavaScript 函数、变量、和常量的命名规范

1. 命名规范

ECMAScript 规范中标识符采用驼峰大小写格式,驼峰命名法由小(大)写字母开始,后续每个单词首字母都大写。根据首字母是否大写,分为两种方式:

  1. Pascal Case 大驼峰式命名法:首字母大写。eg:StudentInfo、UserInfo、ProductInfo
  2. Camel Case 小驼峰式命名法:首字母小写。eg:studentInfo、userInfo、productInfo

标识符,则包括变量、函数名、类名、属性名和函数或类的参数,每个命名方法又略有不同,下面详细解释一下:

2. 函数的命名

函数是执行某些操作的行为。因此,它们的名称通常是动词。名称应简洁、尽可能准确,并描述函数的作用,以便阅读代码的人能大致了解该函数的功能。

一个广泛采用的做法是用动词前缀来命名函数,这些前缀模糊地描述了动作。团队内部应就这些前缀的含义达成一致。

命名方法:小驼峰式命名法。

命名规范:前缀应当为动词。

命名建议:可使用常见动词约定

动词 含义 返回值
can 判断是否可执行某个动作(权限) 函数返回一个布尔值。true:可执行;false:不可执行
has 判断是否含有某个值 函数返回一个布尔值。true:含有此值;false:不含有此值
is 判断是否为某个值 函数返回一个布尔值。true:为某个值;false:不为某个值
get 获取某个值 函数返回一个非布尔值
set 设置某个值 无返回值、返回是否设置成功或者返回链式对象
load 加载某些数据 无返回值或者返回是否加载完成的结果

以下是一些常见前缀及其含义:

  • “get…” – 返回一个值,

  • “calc…” – 计算某些内容,

  • “create…” – 创建某些内容,

  • “check…” – 检查某些内容并返回布尔值,等等。

这类名称的示例:


有了这些前缀,一眼就能从函数名中了解它的作用以及返回值的类型。

函数命名注意事项

一个函数 —— 一个动作

一个函数应当只做其名称所暗示的事情,不多也不少。

两个独立的动作通常应该写成两个函数,即使它们经常一起被调用(这种情况下我们可以写一个第三个函数来调用这两个)。

以下是一些违反该原则的例子:

  • getAge —— 如果它弹出一个显示年龄的警告框,那就不合适(它应该只是获取年龄)。

  • createForm —— 如果它修改了文档并将表单添加到其中,那就不妥(它应该只是创建并返回表单)。

  • checkPermission —— 如果它显示了“允许访问/拒绝访问”的消息,那就不好(它应该只执行检查并返回结果)。

这些例子基于前缀的一般含义。你和你的团队可以就其他含义达成一致,但通常不会有太大差别。无论如何,你应当清楚了解每个前缀的意义,知道带有该前缀的函数应该做什么、不能做什么。所有使用相同前缀的函数都应遵循同一规则,并在团队中达成共识。

超短的函数名称

那些非常常用的函数有时会使用超短的名称。

例如,jQuery 框架定义了一个函数,名称是 $。Lodash 库的核心函数名为 _。

这些是例外。通常情况下,函数名称应简洁且具有描述性。

函数 == 注释

函数应该简短并且只做一件事。如果这件事很大,也许值得将函数拆分成几个更小的函数。有时候遵循这个规则可能并不容易,但它绝对是有益的。

一个单独的函数不仅更容易测试和调试——它的存在本身就是一个很好的注释!

例如,比较下面的两个 showPrimes(n) 函数。每个函数都会输出小于等于 n 的质数

下面第一段CODE使用了标签:


第二段COD使用了一个额外的函数 isPrime(n) 来测试是否为质数

第二段code更容易理解,不是吗?我们看到的是一个动作的名称(isPrime),而不是一段代码。有时人们将这样的代码称为自描述(self-describing)代码。

因此,即使我们不打算重复使用它们,函数仍然可以被创建。它们帮助结构化代码并提高可读性。

3. 变量的命名

命名方法:小驼峰式命名法。

命名规范:前缀应当是名词。(函数的名字前缀为动词,以此区分变量和函数)

命名建议:尽量在变量名字中体现所属类型,如:length、count等表示数字类型;而包含name、title表示为字符串类型。

4. 常量

命名方法:名称全部大写。

命名规范:使用大写字母和下划线来组合命名,下划线用以分割单词。

除教程外,本网站大部分文章来自互联网,如果有内容冒犯到你,请联系我们删除!
Posted in Javascript 函数