这章呢学习的概念性的东西会比较多,但是逻辑的东西并不多。
5.1 函数定义
函数的定义是什么,简单点来说就是起到分装的作用。何为分装?假设我们家里没有衣柜、鞋柜等东西,所有的东西都是堆在一起的,包括衣服、鞋子、被子啊等等,是不是就会显得杂乱无章,这就需要一个分装。什么是分装呢,就是拿一个盒子,把东西分类包装好,下次需要用的时候,直接到盒子里面寻找,这样目的性就比较强了,这就是分装的性质。那么函数分装是什么,函数分装的是过程,也就是说把一个操作过程分装起来,这样就比较好找、好用,这是第一步;第二步呢,函数也可以反过去调用。
5.11 函数声明
函数声明,是一种独立的结构,它会声明一个具名函数,并必须以function开头。且函数声明会进行函数提升,使它能在其所在作用域的任意位置被调用,即后面的代码可以将此函数通过函数名赋值给变量或者对象属性。结构如下:
1 | /*函数的声明 |
例如,以下的代码定义了一个函数名为 reverseNumber 的函数:
1 | //12345返回变成 54321 ,用函数实现 |
5.12 函数表达式(命名、匿名)
虽然上面的函数声明在语法上是一个语句,但函数也可以由函数表达式创建。
1 | //函数表达式 |
函数声明和函数表达式最大的区别是:函数声明的函数名在系统里面可以找到名字,但是,函数表达式不可以。以下代码定义了一个 fact 函数:
1 | var f = function fact(x){ |
我们在浏览器的系统中查找 fact 这个函数名,可以看到,

所以这也是函数声明和函数表达式的最大区别,那么,在这边,我们也可以这样写,两者实现的效果是一样的,
1 | var f = function(x){ |
这个写法大家目前先记住,简而言之,arguments.callee 就是代替表达式的函数名。函数表达式这块呢,大家一定要去理解,因为我们后边学的基本上都是用的函数表达式。
5.13 函数作为参数传递
函数呢,也可以被当作接力棒,作为参数传递给另外一个函数,实例说明下,
1 | //函数可以作为参数传给另外一个函数 |
其实很简单,就是在外面包一层另外的函数,然后在这个另外函数里面执行真正的函数。另外, function 是一个引用类型的对象,看例子:
1 | console.log((f3=function(x){ |
底下我们来看两个值互相交换,要怎么写呢?详解请看下例,
1 | var x=5; |
诶?怎么回事,没有发生交换啊,别慌,再来,
1 | var x=[5]; |
为什么 x,y 的类型换成数组,就可以交换数值了呢?这就是我们为什么要试图去理解引用和值,值在函数里边是换不过来的,但是,如果是引用的话是可以的,因为引用操作的是真实的堆里面的东西。
5.14 嵌套函数
在 JavaScript 中,函数可以嵌套在另一个函数中进行定义,有点类似 Java 中的内部类,
1 | function hypotenuse(a,b){ |
在上面的代码片段中,函数 hypotenuse 中嵌套定义了函数 square 。这时,函数square只能在distance中被调用。如果我们想要在distance之外调用square函数,由于JavaScript中函数执行环境和变量作用域的限制,我们将得到一个很不友好的错误提示!所以,嵌套函数在未来我们讲闭包的时候带来很多很多的问题。
5.2 函数的调用
5.21 函数调用
JavaScript 中函数有4种调用方式,每种方式的不同在于 this 的初始化。一般而言,在 JavaScript 中, this 指向函数执行的当前对象。
作为一个函数调用,
1 | function myFunction(a, b) { |
作为方法调用,
1 | var obj={}; |
作为构造函数调用,构造函数调用这个的话,后面章节会继续深入讲解,
1 | // 3.构造函数 |
间接调用 间接调用和直接调用唯一的区别是可以绑定 this 指针。如果不考虑 this ,下面这三种写法完全一样的。
1 | function hypotenuse(a,b){ |

5.22 形参和实参
什么是形参,什么又是实参?形参和实参是不一样的,数量、类型都可以不一样,形参和实参会绑定,动态关联。
1 | function foo(a,b,c){ |
5.3 递归
递归构造:
- 找到已知 f(x-1) 情况下,如何求解 f(x) 的通式;
- 找到递归的基石,比如 f(0) 、f(1) 的值;
递归真正在工业中是很少使用的,一般是适用于学校性的学习。但是,递归的用法还是挺好用的,主要是考虑到栈的问题,当然,如果系统分配的栈大一点的话,整个递归问题就会进一步得到改善。我们来看个递归的例子:
1 | //递归的例子 |