在本文中,我们展示了如何在 JavaScript 中使用函数。
函数是零个或多个输入参数到零个或多个输出参数的映射。
使用函数,我们可以减少代码的重复性并提高其清晰度。可以使用函数将更复杂的任务分成更简单的步骤。
函数可以分配给变量,作为参数传递给函数或从其他函数返回。
JS函数定义
JS函数是用function关键字定义的。关键字后跟函数名称,用括号括起来并用逗号分隔的函数参数列表,以及用花括号 {} 括起来的函数体。
函数体由JS语句组成。函数使用 return 关键字返回值。
function add(x, y) {
return x + y;
}
let z = add(10, 5);
console.log(z);
该示例定义了一个简单的add 函数。
function add(x, y) {
return x + y;
}
这是函数的定义。它返回一个简单加法表达式的值。它有两个用逗号分隔的参数。使用return 关键字,我们将计算值传递给调用者。
let z = add(10, 5);
函数被调用。它接收整数参数。返回值存储在z 变量中。
JS函数表达式
function 关键字可用于在表达式中定义函数。函数表达式允许我们创建匿名函数。
函数表达式在其他编程语言中被称为lambda表达式。
let z = function add(x, y) {
return x + y;
}
console.log(z(10, 10));
我们用函数表达式重写前面的例子。
let z = function add(x, y) {
return x + y;
}
我们将函数表达式传递给z 变量。
console.log(z(10, 10));
函数是通过z变量调用的。
JS匿名函数
匿名函数没有名字。在许多情况下,定义命名函数是多余的。
setTimeout(
function() {
console.log('Hello there!')
}, 3000
);
setTimeout 函数定义了一个处理函数,该函数在指定的毫秒数后执行。不需要定义命名函数;匿名函数很适合这里。
数组集合包含几个作用于其元素的函数。
let vals = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let res = vals.reduce(function (x, y) { return x + y; });
console.log(res);
reduce函数用于计算JS数组元素的总和。该函数将 reducer 函数作为参数。对数组的所有元素运行 reducer 的结果是总和值。
let res = vals.reduce(function (x, y) { return x + y; });
reducer 函数是一个匿名的 JS 函数。
JS函数默认值
在 JavaScript 中,函数的参数默认为undefined。我们可以给函数参数自定义默认值;如果没有为参数提供值,则使用它们。
function power(a, b = 2) {
if (b == 2) {
return a * a
}
let value = 1
for (let i = 0; i < b; i++) {
value *= a
}
return value;
}
let r1 = power(3)
console.log(r1);
let r2 = power(3, 3)
console.log(r2);
let r3 = power(3, 5)
console.log(r3);
我们创建了一个power 函数。该函数有一个带有隐式值的参数。我们可以用一个或两个参数调用该函数。
$ node main.js 9 27 243
JS 可变函数
可变参数函数可以接受可变数量的参数。例如,当我们想要计算值的总和时,我们可能有四个、五个、六个等值要传递给函数。
我们使用 …(省略号)运算符在 JavaScript 中定义可变参数函数。
function sum(...vals) {
return vals.reduce(function (x, y) { return x + y; });
}
console.log(sum(1, 2));
console.log(sum(1, 2, 3));
console.log(sum(1, 2, 3, 4));
程序定义了一个sum 函数,它可以接受可变数量的参数。
function sum(...vals) {
return vals.reduce(function (x, y) { return x + y; });
}
vals 是一个 JS 数组。我们使用它的reduce 函数来计算值的总和。 reduce 函数需要
$ node main.js 3 6 10
JS箭头函数
箭头函数是一种语法较短的匿名函数。它是用一对包含参数列表的括号定义的,后跟一个粗箭头 (=>) 和一对花括号 {} 分隔主体语句。
如果箭头函数只有一个参数,括号对可以省略。如果它包含单个语句,则花括号也可以省略。
let vals = [-1, 2, 3, -4, 5, 6, -7, 8, 9, 10]; let res = vals.filter(e => e > 0); console.log(res);
在示例中,我们过滤了一个整数数组。 filter 函数将谓词函数作为参数;它定义了过滤的值。谓词是用箭头函数定义的。
JS嵌套函数
嵌套函数,也称为内部函数,是在另一个函数内部定义的函数。
let user = { fname: 'John', lname: 'Doe', occupation: 'gardener' }
function sayHello(u) {
let msg = buildMessage(u);
console.log(msg);
function buildMessage(u) {
return `${u.fname} ${u.lname} is a ${u.occupation}`;
}
}
sayHello(user);
在示例中,我们有一个嵌套的buildMessage 函数,它是在sayHello 函数内部定义的辅助函数。
JS 闭包
闭包 是一个匿名的嵌套函数,它保留对定义在闭包主体之外的变量的绑定。闭包可以拥有自己的独特状态。当我们创建函数的新实例时,状态就会变得孤立。
function intSeq() {
let i = 0;
return function () {
return i++;
};
}
let nextInt = intSeq();
console.log(nextInt());
console.log(nextInt());
console.log(nextInt());
console.log(nextInt());
let nextInt2 = intSeq();
console.log(nextInt2());
console.log(nextInt2());
我们有intSeq 函数,它生成一个整数序列。它返回一个递增 i 变量的闭包。
function intSeq() {
let i = 0;
return function () {
return i++;
};
}
函数中定义的变量具有局部函数作用域。但是,在这种情况下,即使在 i 函数返回后,闭包也绑定到 intSeq 变量。
let nextInt = intSeq();
我们调用intSeq函数。它返回一个函数,该函数将增加一个计数器。返回的函数关闭变量i 以形成闭包。闭包绑定到nextInt 名称。
let nextInt2 = intSeq(); console.log(nextInt2()); console.log(nextInt2());
intSeq 函数的下一次调用返回一个新的闭包。这个新的闭包有自己独特的状态。
$ node main.js 0 1 2 3 0 1
JS高阶函数
高阶函数对其他函数进行操作,要么将它们作为参数,要么通过返回它们。
let vals = [-3, 0, 1, 2, 5, 4, 9, 11, 8, 7];
let isEven = e => e % 2 == 0;
let isOdd = e => e % 2 != 0;
function doFilter(vals, pred) {
let filtered = [];
for (let i = 0; i < vals.length; i++) {
pred(vals[i]) ? filtered.push(vals[i]) : null;
}
return filtered;
}
let res = doFilter(vals, isEven);
console.log(res);
res = doFilter(vals, isOdd);
console.log(res);
doFilter 是高阶函数。
function doFilter(vals, pred) {
let filtered = [];
for (let i = 0; i < vals.length; i++) {
pred(vals[i]) ? filtered.push(vals[i]) : null;
}
return filtered;
}
该函数将谓词函数(谓词是一个产生布尔值的函数)作为参数。它过滤掉所有满足给定谓词的值。
$ node main.js [ 0, 2, 4, 8 ] [ -3, 1, 5, 9, 11, 7 ]
JS成员函数
成员函数是在类定义中定义的函数。成员函数在某些语言中称为方法,包括 Java 和 C#。
class Person {
constructor(firstName, lastName, email) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
info() {
return `${this.firstName} ${this.lastName}, ${this.email}`;
}
}
let person = new Person('John', 'Doe', 'jdoe@example.com');
console.log(person.info());
类是用class关键字定义的。
info() {
return `${this.firstName} ${this.lastName}, ${this.email}`;
}
info 是在类中定义的成员函数。
JS函数构造函数
可以使用函数构造函数创建 JS 对象。它将值作为参数。使用this 关键字设置属性。成员函数是使用this 和函数关键字创建的。使用 new 关键字创建新对象。
function Person(firstName, lastName, email) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.info = function () {
return `${this.firstName} ${this.lastName}, ${this.email}`;
}
}
let person = new Person('John', 'Doe', 'jdoe@example.com');
console.log(person.info());
在程序中,我们定义了一个Person类型。
function Person(firstName, lastName, email) {
Person 的构造函数是用function 关键字定义的。
this.info = function () {
return `${this.firstName} ${this.lastName}, ${this.email}`;
}
在构造函数定义中,我们定义了info 成员函数。
$ node main.js John Doe, jdoe@example.com
JS函数类型
JavaScript 也是一种强大的面向对象语言。每个函数也是一个对象。它的类型是Function。可以使用new Function 构造函数创建函数,但不推荐这样做。
let x = 3;
let y = 8;
let square = new Function('x', 'return x * x');
let res = square(x);
console.log(res);
res = square(y);
console.log(res);
在示例中,我们使用square 构造函数定义了Function 函数。
JS函数提升
提升是在执行代码之前将函数、变量或类的声明移动到其作用域顶部的过程。
console.log(sum(1, 2, 3, 4, 5));
function sum(...vals) {
return vals.reduce((x, y) => x + y);
}
我们在定义之前调用sum 函数。
但是,提升不适用于函数表达式。
console.log(sum(1, 2, 3, 4, 5)); let sum = (...vals) => vals.reduce((x, y) => x + y);
程序以错误结束:ReferenceError: Cannot access 'sum' before initialization。
JS 生成器
生成器是可以退出并稍后重新进入的函数。它们的上下文(变量绑定)在函数调用中保存。使用 function* 语法创建生成器函数。
调用生成器函数返回一个迭代器。当迭代器的next方法被调用时,生成器函数的主体被执行到第一个yield表达式;它返回一个包含生成值的value 属性的对象。 doneproperty 指示生成器是否已生成其最后一个值。
function* idxGen(max) {
let idx = 0;
while (idx < max) {
yield idx++;
}
}
const g = idxGen(100);
for (let i of g) {
console.log(i);
}
该示例创建了一个生成器,它生成的索引达到指定的最大值。
function* idxGen(max) {
let idx = 0;
while (idx < max) {
yield idx++;
}
}
我们定义了idxGen 生成器函数。 yield关键字退出生成器并返回一个值。下次调用迭代器的 next 函数时,我们继续执行 yield 关键字后的行。保留局部 idx 变量。当 idx 达到 max 值时,生成器生成其最后一个值并将 done 属性设置为 true。
const g = idxGen(100);
我们称idxGen;它返回一个迭代器。
for (let i of g) {
console.log(i);
}
在 for 循环中,我们迭代生成的值。
JS IIFE
立即调用函数表达式 (IIFE) 是定义为表达式并在创建后立即执行的函数。它使用函数作用域产生词法作用域。在引入 JS 模块之前,这是一种广泛使用的方法。
let sum = (function (a, b) {
return a + b;
})(15, 50);
console.log(sum);
我们定义了一个带有两个参数的立即执行的加法函数。结果存储在sum 变量中。
$ node main.js 65
在本文中,我们介绍了 JavaScript 函数。
列出所有 JavaScript 教程。
