闭包:主要是解决
1、函数闭包的出现是javascript 无权限概念,一个函数里面有全局变量,
这样就麻烦了,大家都能用,存的时间长,所以闭包里的变量只能自己函数用,
成了私有变量。
2、一个函数也是对象,一个函数可以建立多个实例,那么每次建立实例时不用总是去初始化私有变量。
这样会大大减少工作量和内存。
参考文章:https://stackoverflow.com/questions/111102/how-do-javascript-closures-work?answertab=active#tab-top
1、First-class function:
如果把函数看成是首类函数,哪么这就意味着javascript 语言,可以以把函数的作为参数传递,把函数当返回值,且将他们赋值给变量或将它们存储在数据结构中。
2、a higher-order function:
1>采用一个或多个函数作为参数
2>返回值,是一个函数。
3、 a closure
第一:一个闭包是支持first-class functions的一种方式,
1》它是一个表达式,在它的作用域内({ })能引用变量(当它第一次声明时),
2》 能赋值给一个变量,
3》可以当函数的参数传递,
4》可以当函数的返回值。
第二:或者, a closure 是一个 stack frame,当函数开始执行时分配一个stack frame(这里和java 方法一样),且当函数返回后,并没有释放stack frame(好像一个堆栈框架分配在堆上,而不是堆栈上!)。
例子1:
function sayHello(name) { var text = 'Hello ' + name; var say = function() { console.log(text); } say(); } sayHello('Joe'); 结果: |
例子2:能赋值给一个变量
下面返回一个函数的应用,和java一样,有了引用,就可以和某个对象相连,而这里表示和函数相连。
|
say,say2 变量是指向一个函数的指针。但和Java不一样,这里的引用变量有两个指针,一是指向一个函数,一个隐含的指向一个闭包函数。
上面的代码有一个闭包,因为一个匿名函数 function() { console.log(text); } 是声明在另一个function, sayHello2() 里面. In JavaScript, 如果你使用 function keyword 在另一个函数里面, 你正在建立一个闭包。
在java中,在一个函数返回后,所有的本地变量不再有用,因为stack frame回收了。
在JavaScript, 如果你声明一个函数在另一个函数里面,然后在你调用函数后,本地变量能保持继续可用。例如:调用sayHello2()后,再调用say2(),sayHello2()函数本地变量text继续有效
function() { console.log(text); } // Output of say2.toString();
看看
say2.toString()的输出
, 我们能看见代码指向变量text. 匿名的函数能引用text
变量,这个变量持有'Hello Bob',因为sayHello2()本地变量保存在一个闭包里
.
魔法是在 in JavaScript 里,一个函数应用同时有一个秘密引用建立它的closure — similar to how delegates 是一个方法指针+一个对象的秘密引用.
例 3:和例子2一样
This example shows that the local variables are not copied — they are kept by reference. It is kind of like keeping a stack-frame in memory when the outer function exits!
|
例 4:
所有三个全局函数对同一个闭包公共的引用,因为他们都被声明在单个的setupSomeGlobals()
.里面。
|
The three functions have shared access to the same closure — the local variables of setupSomeGlobals()
when the three functions were defined.
注: that in the above example, 如果你再次调用setupSomeGlobals()
, 然后一个新的 closure (stack-frame!) 被建立.
旧的
gLogNumber
, gIncreaseNumber
, gSetNumber
变量被新函数重写,新函数有一个新的closure. (In JavaScript, 无论你是么时候把一个函数声明在另一个函数里面,当外面的函数重新调用时,里面的函数重新 建立)、
例5: 函数作参数
如果你在一个循环中定义一个函数,闭包中的局部变量不会像您最初想象的那样起作用。
下面表示数组元素是一个函数指针,哪么 fnlist[j](),可以是内部函数调用,但是闭包的item和i没有保存,导致后面调用不起作用。
而且闭包的变量保存item=item3,i=3,中间的数据没有保存。
|
pointer = function() {console.log(item + ' ' + list[i])};
result.push(pointer);
例6:javascript首先把变量移到顶部,然后运行,只要在{}定义的变量,里面所有函数都能用,函数和变量的放置的顺序无关,也是javascript的第一大特点。
sayAlice()=say=指针,指向内部函数。
这里的alice将移到say上面( variable hoisting)),所有匿名函数可以用。
|
例7:函数作为返回值,num,anArray,本地变量保存变化的值。
|
var myObject = (function ( ){ var value = 0; return { increment:function (inc) { value += typeof inc === 'number' ?inc : 1; }, getValue: function ( ) { returnvalue; } }; }( )); |
**(function($, window) { })(mui, window);:就是立即执行,这是一个匿名函数,既然是函数,必须要调用,哪么调用直接放在定义后面(mui, window)
估计是浏览接收一个文件放入自己的缓存后,立即执行这个脚本。