javascript closure

来源:互联网 发布:手机网络看不了视频 编辑:程序博客网 时间:2024/05/16 08:38

闭包:主要是解决

          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一样,有了引用,就可以和某个对象相连,而这里表示和函数相连。

function sayHello2(name) {  var text = 'Hello ' + name; // Local variable  var say = function() { console.log(text); }//赋值给一个变量  return say;}var say2 = sayHello2('Bob');say2(); // logs "Hello Bob"

 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!

function say667() {  // Local variable that ends up within closure  var num = 42;  var say = function() { console.log(num); }  num++;  return say;}var sayNumber = say667();sayNumber(); // logs 43

例 4:

  所有三个全局函数对同一个闭包公共的引用,因为他们都被声明在单个的setupSomeGlobals().里面。

var gLogNumber, gIncreaseNumber, gSetNumber;function setupSomeGlobals() {  // Local variable that ends up within closure  var num = 42;  // Store some references to functions as global variables  gLogNumber = function() { console.log(num); }  gIncreaseNumber = function() { num++; }  gSetNumber = function(x) { num = x; }}setupSomeGlobals();gIncreaseNumber();gLogNumber(); // 43gSetNumber(5);gLogNumber(); // 5var oldLog = gLogNumber;setupSomeGlobals();gLogNumber(); // 42oldLog() // 5

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!) 被建立.

旧的gLogNumbergIncreaseNumbergSetNumber 变量被新函数重写,新函数有一个新的closure. (In JavaScript, 无论你是么时候把一个函数声明在另一个函数里面,当外面的函数重新调用时,里面的函数重新 建立)、

例5:   函数作参数

        如果你在一个循环中定义一个函数,闭包中的局部变量不会像您最初想象的那样起作用。

         下面表示数组元素是一个函数指针,哪么 fnlist[j](),可以是内部函数调用,但是闭包的item和i没有保存,导致后面调用不起作用。

而且闭包的变量保存item=item3,i=3,中间的数据没有保存。

function buildList(list) {    var result = [];    for (var i = 0; i < list.length; i++) {        var item = 'item' + i;        result.push( function() {console.log(item + ' ' + list[i])} );    }    return result;}function testList() {    var fnlist = buildList([1,2,3]);    // Using j only to help prevent confusion -- could use i.    for (var j = 0; j < fnlist.length; j++) {        fnlist[j]();    }} testList() //logs "item2 undefined" 3 times

pointer = function() {console.log(item + ' ' + list[i])};result.push(pointer);
例6:javascript首先把变量移到顶部,然后运行,只要在{}定义的变量,里面所有函数都能用,函数和变量的放置的顺序无关,也是javascript的第一大特点。
sayAlice()=say=指针,指向内部函数。
这里的alice将移到say上面( variable hoisting)),所有匿名函数可以用。

function sayAlice() {    var say = function() { console.log(alice); }    // Local variable that ends up within closure    var alice = 'Hello Alice';    return say;}sayAlice()();// logs "Hello Alice"

7:函数作为返回值,num,anArray,本地变量保存变化的值。

function newClosure(someNum, someRef) {    // Local variables that end up within closure    var num = someNum;    var anArray = [1,2,3];    var ref = someRef;    return function(x) {        num += x;        anArray.push(num);        console.log('num: ' + num +            '; anArray: ' + anArray.toString() +            '; ref.someVar: ' + ref.someVar + ';');      }}obj = {someVar: 4};fn1 = newClosure(4, obj); //返回内部匿名函数的指针。fn2 = newClosure(5, obj);fn1(1); // num: 5; anArray: 1,2,3,5; ref.someVar: 4;//调用内部函数fn2(1); // num: 6; anArray: 1,2,3,6; ref.someVar: 4;obj.someVar++;fn1(2); // num: 7; anArray: 1,2,3,5,7; ref.someVar: 5;fn2(2); // num: 8; anArray: 1,2,3,6,8; ref.someVar: 5;

例子8:函数在参数里面.表示私有函数,执行完,里面的数据全部清除。
   
 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)

      估计是浏览接收一个文件放入自己的缓存后,立即执行这个脚本。








原创粉丝点击