介绍
假设您有一个文件,该文件长82行,并且仅由一系列语句组成。 (我希望这不是真的,但是一切皆有可能。)您如何理解该程序的作用? 您将如何修改或使用它? 用这种代码很难做任何事情,因为它没有结构。
要解决此问题,可以使用函数。 函数是一组执行特定任务的语句。 函数使我们可以将程序分解为较小的程序,从而使我们的代码更具可读性,可重用性和可测试性。
内容
- 虚函数
- 值返回功能
- 范围
- 参量
- 模组
虚函数
这种功能列出了程序要执行的步骤。 考虑到我们正在编写一个程序来将用户登录到网站。 该程序可能包含以下任务:
- 获取用户名
- 取得密码
- 检查用户名和密码是否存在
- 将用户重定向到其仪表板
每个步骤都可能包含在登录功能中。 这是一个示例函数:
function greet() {
console.log("Hello, World");
}
这是函数的一般形式:
function functionName() {
statement;
statement;
etc.
}
要执行该功能(也称为调用该功能或调用该功能),请编写一条调用该语句的语句。
greet();
()
是我们将输入传递给函数的地方。 当我们定义函数时,输入称为参数。 当我们调用函数时,输入将是实际值,称为参数。 例:
function greet(name) {
console.log("Hello, " + name);
}
greet("Alberta"); //Hello Alberta
使用JavaScript ES6,可以使用箭头语法定义函数。 这是使用箭头语法定义的问候函数:
let greet = () => console.log("Hello, World");
具有一个参数的函数:
let greet = name => console.log("Hello, " + name);
一个具有多个参数的函数:
let greet = (fname, lname) => console.log("Hello, " + fname + " " + name);
具有多个语句的函数:
let greet = (fname, lname) => {
let name = fname + " " + name;
console.log("Hello, " + name);
}
因为箭头函数是匿名函数,所以我们通过将函数赋给变量来为其命名。 当您的函数主体只有一个语句时,箭头函数会很有用。
值返回功能
这种函数返回一个值。 该函数必须以return语句结尾。 本示例返回两个数字的和。
function add(x, y) {
return x + y;
}
这是定义值返回函数的一般形式:
function functionName() {
statement;
statement;
etc.
return expression;
}
expression的值是该函数输出的值。 当将函数存储在变量中时,此函数很有用。
let variableName = functionName();
范围
变量的范围是程序中可以访问变量的部分。 变量可以是局部变量或全局变量。 局部变量的作用域在创建它的函数内部。该函数外部的任何代码都不能访问其局部变量。
同样,当您使用let
或const
声明变量时,它们具有块作用域。 块是一组在一起属于一组的语句。 块就像将我们的代码用大括号括起来一样简单:
{
let a = 2;
}
变量a
是它所在的块的局部变量。块也可以是循环或if语句。 例:
let a = 1;
if (5 >4){
let a = 2;
}
console.log(a); //1
由于我们的控制台语句与第一个变量a
处于同一范围内,因此它将显示该值1。它无法访问if块中的变量。 现在,考虑以下示例:
let a = 1;
if (5 >4) {
let a = 2;
console.log(a); //2
}
现在将显示2,因为控制台语句可以访问的变量范围在if块内。 函数的参数也是局部变量,只能由函数内部的代码访问。 另一方面,全局变量可以由程序文件中的所有语句访问。 例:
let a = 1;
function foo () {
a = 2;
}
console.log(a); //1
foo();
console.log(a); //2
在此示例中, a
是全局变量,我们可以在foo函数中对其进行访问。 第一控制台语句将显示1.呼叫后foo
,的值a
被设置为2,使得第二控制台语句显示器2。
全局变量应该很少使用,理想情况下根本不使用。 由于全局变量可以由程序的任何部分访问,因此存在以不可预测的方式进行更改的风险。 在具有数千行代码的大型程序中,它使程序更难以理解,因为您不容易看到变量的使用方式。 最好创建和使用局部变量。
但是,如果需要在程序的多个位置使用变量,则可以使用全局常量。 使用const
关键字声明变量可防止对其进行更改,从而使其更安全地使用。 您只需要担心在声明常量的位置更新常量的值。
参量
回想一下,参数是函数用来接收数据的变量。 调用函数时,会为参数分配函数参数的值。 从ES6开始,也可以使用parameterName=value
格式为parameterName=value
提供默认值。 在这种情况下,可以调用不带参数的函数,它将使用默认值。 例:
function greet (name="world") {
console.log("Hello, " + name);
}
greet(); //Hello World
扩展/剩余运算符是ES6的新增功能,可用于将数组或对象扩展为单个值,或将函数的参数收集为数组。 这是使用rest参数的示例:
function foo(...args) {
console.log(args);
}
foo( 1, 2, 3, 4, 5); //[1, 2, 3, 4, 5]
模组
假设现在您有一个包含1,082行的文件。 (我已经看到了,如果遇到这种情况,应该运行。)该文件被组织成函数,但是很难看到它们之间的关系。
要将相关行为归为一组,我们应该将代码放入模块中。 ES6中的模块是一个包含相关功能和变量的文件。 模块使我们可以隐藏私有属性,并公开我们要在其他文件中使用的公共属性。 文件名将是模块的名称。 模块也有自己的范围。 要使用超出模块范围的变量,必须将其导出。 未导出的变量将是私有的,只能在模块内访问。
单个属性可以这样导出:
export function foo() {
console.log(“Hello World”);
}
export let bar = 82;
export let baz = [1,2,3];
或者,可以使用一个导出语句导出所有属性:
function foo() {
console.log("Hello World");
}
let bar = 82;
let baz = [1,2,3];
export { foo, bar, baz };
要使用模块的变量,请将其导入到文件中。 您可以这样指定要从模块导入的内容:
import { foo, bar, baz } from "foo";
您还可以重命名导入:
import { foo as Foo } from "foo";
Foo();
或者,您可以导入模块的所有属性:
import * as myModule from "foo";
myModule.foo();
评论
函数使我们能够将程序划分为易于管理的较小程序。 这种做法称为模块化。 函数有两种:void函数和值返回函数。 void函数在其中执行语句。 值返回函数为我们提供了一个值。
作用域是程序中可以访问变量的部分。 函数内部声明的变量(包括函数的参数)是局部变量。 块也有作用域,可以在它们内部创建局部变量。
未包含在块或模块中的变量将是全局变量。 如果需要全局变量,则可以使用全局常量。 否则,请尝试将代码包含在模块中,因为模块具有自己的作用域。 但是更好的是,模块可以提供您的代码结构和组织。