JavaScript 基础(二):函数

JavaScript 基础(二):函数

在本文中,将专注于在 JavaScript 中定义自己的自定义函数,介绍函数的定义方式、声明、作用域及参数定义。

函数定义

一个函数可以看作是包裹在一个变量中的一段代码,它允许一遍又一遍地重用调用那段代码。在本文中,将讨论在 JavaScript 中定义函数的三种不同方式。

第一种方法是将函数定义为值,并将该值赋值给一个变量(就像《JavaScript 基础(一):语法和程序结构》中定义变量的方式一样),而这个变量就成为了一个函数类型。

const square = function (x) {
    return x * x;
};

该函数是使用关键字 function 创建的,它将接受一个参数 x 作为输入。函数还应该有一个主体,可以在其中使用关键字 return 返回输出,或者具有某种副作用。

最后,作为值的函数将被赋值给变量 square,需要使用它来执行/调用此函数,例如:

console.log(square(2));

另外,请记住末尾的英文分号 ; 建议必须输入,如果怕忘记,可以交给代码编辑器自动完成。

一个函数可以有多个参数或根本没有参数,如下:

let sleep = function () {
    console.log(" 3 秒过去了……");
};
var multiply3 = function (x, y, z) {
    return x * y * z;
};

第二种方法稍微简单一些,同样通过使用 function 关键字声明一个函数,并且它不需要在函数末尾使用英文分号;

function square(x) {
    return x * x;
}

此种定义方式允许调用在前(上面第一种方式不可以),定义在后,如下:

console.log(square(2));
function square(x) {
    return x * x;
}

在这里,将函数声明放在调用它们的语句之后,代码仍然有效。这样可以在代码组织的时候将所有的函数放在一块或者一个文件中,对于代码维护来说比较友好。

如果函数只有一个参数,则可以省略参数列表周围的括号(但为了代码的统一性不建议这么做)。而如果函数体中只有一条语句,大括号和 return 关键字也可以省略。

const square = (x) => x * x;

声明和作用域

在深入探讨函数的主题之前,回顾一下函数定义的第一种方法。可能已经注意到,在示例中使用不同的关键字 letconstvar 定义了函数。它们的区别究竟是什么?本文就不细说了,如有兴趣了解可以参阅《细说 javascript 中变量声明 var、let、const 的区别》。

总的来说,letconst 字面上的意思,const 代表常量,意味着一旦使用 const 声明绑定,就无法更改其值(当然数组和对象是有所区别),let 声明的绑定后续是可以改变的。

可选参数

JavaScript 在传递给函数的参数数量方面非常松散,例如,有之前定义的 square() 函数,理论上它应该只接受一个参数。但实际上,看下面代码:

function square(x) {
    return x * x;
}
console.log(square(2, true, "test"));

在调用的时候多传入参数并不会出现什么错误与异常,函数会忽略了额外的参数并计算第一个参数的平方。如果传递的参数太少,那些丢失的参数将被赋值为 undefined 而不是错误。

当然,这样做的缺点是,很容易出现错误。所以,即使它在程序上有效,也不应该依赖它,这可能会给程序带来一些意想不到的结果。因此建议在编写代码的时候还是按照严格的方式,这些现在都可以借助工具来自动检查或者完成。

REST参数

但是,如果不知道需要多少参数怎么办?例如,需要设计一个函数来查找一系列数字中的最大数字,但不知道该系列中有多少个数字,因此需要设计一个接受任意数量参数的函数。有两种方式可以实现,一个是REST参数,一个是 arguments 对象。

REST参数就是在参数面前输入三个点,如下:

function max(...numbers) {
    let result = -Infinity;
    for (const number of numbers) {
        if (number > result) {
            result = number;
        }
    }
    return result;
}
const result = max(1, 2, 3, 4, 5, 6, 7);
console.log(result); // 7

在函数中执行 console.log(typeof numbers) ,输出为 object 。REST参数适用于 ES6 中的箭头函数。

而使用 arguments 对象,在函数定义的时候无需定义变量,如下:

function max() {
    let result = -Infinity;
    const numbers = [...arguments];
    for (const number of numbers) {
        if (number > result) {
            result = number;
        }
    }
    return result;
}
const result = max(1, 2, 3, 4, 5, 6, 7);
console.log(result); // 7

在函数中执行 console.log(typeof arguments) ,输出同样为 object 。对象 arguments 是所有函数中可用的局部变量,可以使用 arguments 对象在函数中引用函数的参数。该对象包含传递给函数的每个参数的条目,这将帮助了解这些参数的数量并使用 arguments 对象访问它们。

对象 arguments 不适用于 ES6 中的箭头函数。