js 两个圆括号 自调用 闭包

JavaSript 圆括号的使用

先来看一组通过函数声明来定义的函数:

先附代码:

 

js 两个圆括号 自调用 闭包_第1张图片

运行结果如下:

js 两个圆括号 自调用 闭包_第2张图片

这里我们可以看出:

Ø  若没有加圆括号,则返回的是这个函数的内容

Ø  若加上圆括号,则返回的是函数执行后的内容

因此圆括号的作用是作为函数的调用运算符,如果函数使用return语句给出一个返回值,那么这个返回值就是整个调用表达式的值。否则,调用表达式的值就是undefined.

接下来看一组通过函数表达式定义的函数

先附代码:

js 两个圆括号 自调用 闭包_第3张图片

运行结果如下图:

js 两个圆括号 自调用 闭包_第4张图片

对于普通函数的调用,函数的返回值成为调用表达式的值。如果该函数返回时因为解释器到达结尾,返回值就是undefined。如果函数返回时因为解释器执行到一条return语句,返回值就是return之后的函数表达式,如果return语句没有值,则返回undefined.

注意:当方法的返回值是一个对象,这个对象还可以再调用他的方法。这种方法调用系列中(通常称为“链”或者“级联”)每次的调用结果都是另外一个表达式的组成部分。

注意:JSfunction是对象。

函数的自调用

首先看一个匿名函数的自调用

先附代码:

js 两个圆括号 自调用 闭包_第5张图片

输出结果:

也就是说自调用会执行函数里面的代码。

再看两例代码对比,来理解闭包这个概念

代码1                                                                                                代码2

js 两个圆括号 自调用 闭包_第6张图片js 两个圆括号 自调用 闭包_第7张图片

运行结果如下:

代码1                               代码2

               

我们来试图理解这句话:

Ø  每次调用JS函数时,都会为之创建一个新的对象用来保存局部变量,把这个对象添加至作用域链中,当函数返回时,就从作用域链中将这个绑定变量的对象删除。如果不存在嵌套的函数,也就没有其他引用指向这个绑定对象,他就会被当作垃圾回收掉。

Ø  如果定义了嵌套的函数,每个嵌套的函数都各自对应一个作用域链,并且将这个作用域链指向一个变量绑定对象。但是如果这些嵌套的函数对象在外部函数中保存下来,那么他们也会和所指向的变量绑定对象一样当作垃圾回收。

Ø  但是如果这个函数定义了嵌套的函数,并将它作为返回值返回或者存储在某处的属性里,这时就会有一个外部引用指向这个嵌套的函数。他就不会被当作垃圾回收,并且它所指向的变量绑定对象也不会被当作垃圾回收。

//上文摘自JS权威指南。

在案例1中,函数add是一个自调用函数。我们将逐句对应解释示例1的运行结果:

12-17 用匿名函数表达式来定义了add函数,需要注意的是这个匿名函数是个自调用函数。

13 设置了counter=0;

14-15 定义了返回function(){ return  ++count;}, 也就是说add函数执行的语句为function(){ return  ++count;}

执行第一次,我们绘出add的运行期上下文作用链表:

js 两个圆括号 自调用 闭包_第8张图片

由于可以访问到counter=1 ,add()=1;

执行第二次,继续执行++counter counter=2,add()=2;

执行第三次,继续直接执行++counter  counter=3,add()=3

我认为的闭包是这样的,count变量不属于全局变量,但是又在add函数内部被定义成私有变量,于是就规定它为嵌套函数作用域对象的部分,且这个嵌套函数有没有被外部函数所保存,不会被当作垃圾回收。这就是为什么count值被循环利用的原因。

/****************************************************************

案例2的作用域链表

js 两个圆括号 自调用 闭包_第9张图片

根据JS权威指南的讲解,count变量在外部函数中保存了下来,那么他们也会和所指向的变量绑定对象一样当作垃圾回收。所以作用值会被覆盖。结果一直都是1的原因。

 

你可能感兴趣的:(js 两个圆括号 自调用 闭包)