09-函数基础
晴空闲云 613 1

本节目标

  1. 掌握函数定义的4种方式:常规函数、匿名函数、箭头函数、构造器函数。
  2. 掌握函数不定参数的声明方式。
  3. 了解js语言中的内置函数。

内容摘要

本篇介绍了js中函数定义的4种方式:常规函数、匿名函数、箭头函数、构造器函数,以及不定参数的声明方式 ...args。

阅读时间30~40分钟。

函数简介和使用

基本上所有的高级语言都支持函数,JavaScript也不例外。JavaScript的函数不但是“头等公民”,而且可以像变量一样使用,也是一种数据类型,具有非常强大的抽象能力。

js中定义函数有4种方式:

1. 常规函数
2. 匿名函数
3. 箭头函数
4. 构造器函数

下面依次对每个函数进行讲解。

常规函数

函数声明通过 function 关键词进行声明,有三个要素:函数名、函数参数、返回值。

语法结构:

function 函数名([参数1, 参数2, ...]) {
    代码块
    [return 返回值]
}

其中:

函数名,表示函数的名字,js中一般采用驼峰命名法。
参数可选,可以不传参数,也可以传入若干个参数。
return为可选,函数体内部的语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回。

函数声明完成之后,正常是给其他地方调用的,调用语法如下:

没有返回值: 函数名(参数1, 参数2, ...)
有返回值:let 变量名 = 函数名(参数1, 参数2, ...)
函数名.call()
函数名.apply()

其中:

有返回值的函数,一般可以用变量进行接收,也可以直接使用。
call和apply是函数对象的方法,也可以起到调用函数的目的。

示例1,声明一个函数,打印:Hello function:

function print() {
    console.log("Hello function");
}

这边我们尝试查看 print 函数的类型:

console.log(type of print); // function

是一个函数类型,具体来说是一个函数对象,正因为是对象,所以可以有属性和方法,call和apply就是其中的方法。

下面调用函数:

print(); // 常规调用
print.call(); // call调用
print.apply(); // apply调用

其中:

call和apply也是调用函数的两种方式,这种方式可以改变this的指向。我们在面向对象章节会再细讲。

注意:

这边这个函数没有返回值,对于没有返回值的函数,如果用一个变量接收,那么就是undefined。
let result = print();
console.log(result); // undefined

示例2,声明一个函数,传入三角形的底和高,返回三角形的面积。

function area(d, h) {
    return d * h / 2;
}

声明好后,调用:

let result = area(10, 5);
console.log(result); // 25

console.log(area.call(null, 10, 5)); // call调用
console.log(area.apply(null, [10, 5])); // apply调用

其中:

call方法,第一个参数表示传入的对象,后面罗列area方法需要的参数。
apply方法,第一个参数表示传入的对象,后面用数组罗列area方法需要的参数。

匿名函数

上面声明的函数有显式的名字,js中也可以声明没有名字的函数,俗称匿名函数。

只是如果函数如果没有名字,要怎么调用呢?所以需要将匿名函数赋值给一个变量。

语法:

let 变量名 = function([参数1, 参数2, ...]){
    代码块
    [return 返回值]
}

其中:

匿名函数没有函数名,但是匿名函数可以赋值给变量,所以可以通过变量调用该函数。

示例1,声明一个匿名函数,打印:Hello,我是一个匿名函数,可以通过变量名对我进行调用。

let printHello = function () {
    console.log("Hello,我是一个匿名函数,可以通过变量名对我进行调用。");
};

调用该函数:

printHello();

既然f是一个变量,那应该有数据类型,我们通过 typeof 查看f的数据类型:

console.log(typeof printHello); // function

可以发现函数 printHello 是一个 function 类型,事实上js中函数也是一个变量类型,并且也是一个对象。

箭头函数

箭头函数是es6推出的一个新的语法,箭头函数表达式的语法比函数表达式更简洁。 箭头函数表达式更适用于那些本来需要匿名函数的地方,并且它不能用作构造函数。

语法:

([参数1, 参数2, ...]) => 代码块

其中:

上面三个点是表示省略号,表示参数可以有多个。

示例1,声明一个箭头函数,返回1个随机数:

let randNum = () => {
    return Math.random();
}

调用方法并打印返回值:

console.log(randNum());

示例2,声明一个箭头函数,传入两个参数,返回和。

let sum = (a, b) => {
    return a + b;
};

调用方法并打印返回值:

console.log(sum(1, 2));  // 3

构造器函数

在js可以使用new Function声明函数。

语法结构:

new Function('x', 'y', 'return x * y;');

其中:

前面若干个是函数的参数,最后一个是代码块。

示例1,声明一个函数,传入三个数字,然后求积。

let f = new Function('x', 'y', 'z', 'return x * y * z;');

调用这个函数:

console.log(f(1, 2, 3)); // 6

通过这边我们可以发现,函数居然可以new出来,那么函数难道也是一个对象?

是的,函数也是一个对象,后面我们在讲解原型链的时候,会再提这个话题。

arguments 变量

每一个函数都有一个 arguments 对象,它包括了函数所有的参数,是一个数组对象。

简单示例:

function f(a, b) {
    // 打印 arguments 对象
    console.log(arguments);
    // 打印 arguments 的类型
    console.log("arguments类型是:" + typeof arguments);
    // 打印 参数 个数
    console.log("传递了几个参数:" + arguments.length);
    // 遍历打印参数
    for (let i in arguments) {
        console.log("第" + i + "个参数是:" + arguments[i]);
    }
}

调用函数,并传递两个参数:

f(1, 2)

这个正常的调用,控制台打印结果如下:

Arguments(2) [1, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ]
arguments类型是:object
传递了几个参数:2
第0个参数是:1
第1个参数是:2

当然js中调用函数,不一定要按照他声明的参数个数,可以是1个,也可以是2个、3个等等,如:

f(1)
f(1, 2, 3)

其中 f(1, 2, 3) 控制台打印结果如下:

Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
arguments类型是:object
传递了几个参数:3
第0个参数是:1
第1个参数是:2
第2个参数是:3

怎么样,是不是又惊呆了!原来js还可以这么玩。

示例1,声明一个函数,传入的参数不定,计算所有传入的参数的和,并返回。

因为参数不定,所以我们需要通过 arguments 获取。

function f() {
    let sum = 0;
    for(let i in arguments) {
        sum += arguments[i];
    }
    return sum;
}

不定参数

因为 arguments 的使用过于隐秘,至少你在调用函数的时候,无法直观的看出需要几个参数,所以es6推出了不定参数的写法。

语法结构:

function 函数名(...参数名) {
    代码块
    return 返回值
}

其中:

三个点不是表示省略号,是不定参数的语法。

简单示例:

function f(...args) {
    // 打印 args 对象
    console.log(args);
    // 打印 args 的类型
    console.log("args类型是:" + typeof args);
    // 打印 参数 个数
    console.log("传递了几个参数:" + args.length);
    // 遍历打印参数
    for (let i in args) {
        console.log("第" + i + "个参数是:" + args[i]);
    }
}

调用函数:

f(1, 2, 3)

控制台打印结果如下:

(3) [1, 2, 3]
args类型是:object
传递了几个参数:3
第0个参数是:1
第1个参数是:2
第2个参数是:3

我们可以发现,这个args货真价实是一个数组了。

因为这种定义不定参数的方式是显式的,所以一般推荐都用这种方式。

系统函数

上面我们可以通过定义函数的语法,定义自己需要的函数,当然js语言也内置了非常多的函数,可以供调用。

如之前学习过的 alert、confirm、prompt 等函数,还有 parseInt、parseFloat、IsNaN、setTimeout、setInterval 等等。

其实这些函数都是 window 对象下的方法,后面讲解 bom 对象是会再进行详细说明。

本节总结

  1. js中函数定义有4种方式:常规函数、匿名函数、箭头函数、构造器函数。
  2. js函数的参数可以是不确定的,推荐使用显式的 ...args 声明。
  3. js内置了非常多的系统函数,可以直接调用。

练习题

  1. 为什么要使用函数?
  2. js中函数有几种声明方式?
  3. 定义一个计算圆面积的函数areaOfCircle(),它有两个参数:r: 表示圆的半径;pi: 表示π的值,如果不传,则默认3.14。
  4. 声明一个匿名函数,传入1个数字,求绝对值。
  5. 声明一个不定参数的函数,计算所有传入参数的和。
  6. 声明一个函数,输入一个整数n, 返回 1!+2!+3!+4!+…n!,另外再使用1个函数封装n!。
  7. 求出所有的水仙花数,使用函数封装判断一个数是否是水仙花数。
  8. call和apply的区别和作用。
评论区

索引目录