在我们之前的教程中,我们讨论了javascript 中的循环。其中一项任务要求您编写一个循环来计算数字的阶乘。假设您必须计算 10 的阶乘,并且您编写了一个 for 循环来执行此操作。然后,有人让你计算其他 20 个数字的阶乘。一次又一次地重写同一个循环来改变一个值是不切实际的。
如果您只编写一次循环并将要计算其阶乘的数字作为可以传递给循环的参数会怎么样?这正是函数所做的,它节省了大量时间和代码重复。
函数是一组执行特定任务的语句。函数允许我们将一个程序分解成更小的程序,使我们的代码更具可读性、可重用性和可测试性。
空函数
值返回函数
范围
参数
模块
空函数
我上面提到的阶乘函数有两种工作方式。一种可能是它可以直接输出计算出的答案。在这种情况下,它不会给我们任何可以分配给其他变量的东西。它只会输出答案。这种不返回任何内容的函数称为 void 函数。
这是函数的一般形式:
function functionName() { statement; statement; etc. }
这是 void 函数的示例:
function greet() { console.log("Hello, World"); }
要执行函数(也称为调用函数或调用函数),您需要编写调用它的语句。
greet();
我想指出 void 函数实际上确实返回undefined了,因为返回一些东西表明该函数已经完成了它的执行。
这 ()是我们将输入传递给函数的地方。当我们定义函数时,输入称为参数。当我们调用函数时,输入将是实际值,称为参数。这是一个例子:
function greet(name) { console.log(`Hello, ${name}`); } // Outputs: Hello, Alberta greet("Alberta");
使用 JavaScript ES6,您可以使用箭头语法定义函数。这是我们greet()使用箭头语法定义的函数:
let greet = () => console.log("Hello, World");
具有一个参数的函数:
let greet = name => console.log(`Hello, ${name}`); // Outputs: Hello, Monty greet("Monty");
具有多个参数的函数:
let greet = name => console.log(`Hello, ${name}`); // Outputs: Hello, Monty greet("Monty");
具有多个语句的函数:
let greet = (fname, lname) => { let name = `${fname} ${lname}`; console.log(`Hello, ${name}`); } // Outputs: Hello, Monty Shokeen greet("Monty", "Shokeen");
因为箭头函数是匿名函数,所以我们通过将其分配给变量来为函数命名。箭头函数的优点之一是它们可以使代码更紧凑。
如果我们将阶乘函数写成 void 函数,它可能看起来像这样:
function factorial(x) { let result = 1; while(x > 1) { result *= x; x -= 1; } console.log(result); } // Outputs: 3628800 factorial(10); // Outputs: 479001600 factorial(12); // Outputs: 6402373705728000 factorial(18);
价值回归函数
这种函数返回一个值。该函数必须以 return 语句结束。此示例返回两个数字的总和。
function add(x, y) { return x + y; }
这是定义返回值函数的一般形式:
function functionName() { statement; statement; //... return expression; }
表达式的值是函数输出的值。这种函数在其返回值存储在变量等中时很有用。基本上,如果您打算在代码中的其他地方使用该值,则应该显式地从函数返回值。
这是我们写成返回值函数的阶乘函数。
function factorial(x) { let result = 1; while(x > 1) { result *= x; x -= 1; } return result; } // Outputs: 3628800 console.log(factorial(10)); // outputs: 479001600 console.log(factorial(12)); // Outputs: 6402373705728000 console.log(factorial(18));
如您所见,我们得到了相同的输出。唯一改变的是我们使用return语句从函数中获取计算值。
范围
变量的范围是程序中可以访问变量的部分。变量可以是局部的或全局的。局部变量的作用域在创建它的函数内部。函数外部的任何代码都不能访问它的局部变量。
此外,当您使用let或const声明变量时,它们具有块作用域。块是一组属于一个组的语句。一个块可以像用花括号包裹我们的代码一样简单:
{ let a = 2; }
该变量a是它所在的块的局部变量。块也可以是循环或 if 语句。例如:
let a = 1; if (true) { let a = 2; } console.log(a); //1
因为我们的控制台语句与我们的第一个变量在同一范围内a,所以它显示该值,即 1。它无权访问 if 块内的变量。现在,考虑这个例子:
let a = 1; if (true) { 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. 在这种情况下,您可以调用不带参数的函数,它将使用默认值。例如:
function greet (name="World") { console.log(`Hello, ${name}`); } // Outputs: Hello, World greet();
spread/rest 运算符是 ES6 的新功能,可用于将数组或对象扩展为单个值或将函数的参数收集到数组中。这是使用 rest 参数的示例:
function foo(...args) { console.log(args); } foo( 1, 2, 3, 4, 5); //[1, 2, 3, 4, 5]
模块
假设现在您有一个超过 1,000 行的文件。该文件按功能组织,但很难看出它们之间的关系。
为了将相关行为组合在一起,我们应该将代码放入模块中。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 函数返回undefined. 一个值返回函数给我们返回一个值。
范围是程序中可以访问变量的部分。在函数内部声明的变量,包括函数的参数,都是局部变量。块也有作用域,可以在其中创建局部变量。
未包含在块或模块中的变量将是全局变量。如果你需要一个全局变量,那么有一个全局常量是可以接受的。否则,请尝试将您的代码包含在模块中,因为模块有自己的范围。但更好的是,模块为您提供了代码结构和组织。
发表评论