zoukankan      html  css  js  c++  java
  • javascript闭包

    闭包的定义:
    •闭包就是函数的局部变量集合,只是这些局部变量在函数返回后会继续存在。
    •闭包就是就是函数的“堆栈”在函数返回后并不释放,我们也可以理解为这些函数堆栈并不在栈上分配而是在堆上分配
    •当在一个函数内定义另外一个函数就会产生闭包
    做为局部变量都可以被函数内的代码访问,这个和静态语言是没有差别。闭包的差别在于局部变量可以在函数执行结束后仍然被函数外的代码访问。这意味着函数必须返回一个指向闭包的"引用",或将这个"引用"赋值给某个外部变量,才能保证闭包中局部变量被外部代码访问。当然包含这个引用的实体应该是一个对象,因为在Javascript中除了基本类型剩下的就都是对象了。
    1 function greeting(name) {
    2      var text = 'Hello ' + name; // local variable
    3      // 每次调用时,产生闭包,并返回内部函数对象给调用者
    4      return function () { alert(text); }
    5 }
    6 var sayHello=greeting( "Closure" );
    7 sayHello()  // 通过闭包访问到了局部变量text

    上述代码的执行结果是:Hello Closure,因为sayHello()函数在greeting函数执行完毕后,仍然可以访问到了定义在其之内的局部变量text

    例子1:闭包中局部变量是引用而非拷贝
    1 function say667() {
    2     // Local variable that ends up within closure
    3     var num = 666;
    4     var sayAlert = function() { alert(num); }
    5     num++;
    6     return sayAlert;
    7 }
    8 var sayAlert = say667();
    9 sayAlert();
    因此执行结果应该弹出的667而非666。
    例子2:多个函数绑定同一个闭包,因为他们定义在同一个函数内
     1 function setupSomeGlobals() {
     2     // Local variable that ends up within closure
     3     var num = 666;
     4     // Store some references to functions as global variables
     5     gAlertNumber = function() { alert(num); }
     6     gIncreaseNumber = function() { num++; }
     7     gSetNumber = function(x) { num = x; }
     8 }
     9 setupSomeGolbals(); // 为三个全局变量赋值
    10 gAlertNumber(); //666
    11 gIncreaseNumber();
    12 gAlertNumber(); // 667
    13 gSetNumber(12);//
    14 gAlertNumber();//12

    例子3:当在一个循环中赋值函数时,这些函数将绑定同样的闭包

     1 function buildList(list) {
     2     var result = [];
     3     for (var i = 0; i < list.length; i++) {
     4         var item = 'item' + list[i];
     5         result.push( function() {alert(item + ' ' + list[i])} );
     6     }
     7     return result;
     8 }
     9  
    10 function testList() {
    11     var fnlist = buildList([1,2,3]);
    12     // using j only to help prevent confusion - could use i
    13     for (var j = 0; j < fnlist.length; j++) {
    14         fnlist[j]();
    15     }
    16 }
    testList的执行结果是弹出item3 undefined窗口三次,因为这三个函数绑定了同一个闭包,fnlist[j]()调用的实际上是function() {alert(item + ' ' + list[i])},而item的值为最后计算的结果,即当前var item = 'item' + list[2];时的结果,此时内存中的i的值已经变为3,list[3]的结果为undefined.
    例子4:外部函数所有局部变量都在闭包内,即使这个变量声明在内部函数定义之后
    1 function sayAlice() {
    2     var sayAlert = function() { alert(alice); }
    3     // Local variable that ends up within closure
    4     var alice = 'Hello Alice';
    5     return sayAlert;
    6 }
    7 var helloAlice=sayAlice();
    8 helloAlice();
    执行结果是弹出”Hello Alice”的窗口。即使局部变量声明在函数sayAlert之后,局部变量仍然可以被访问到。
    例子5:每次函数调用的时候创建一个新的闭包
     1 function newClosure(someNum, someRef) {
     2     // Local variables that end up within closure
     3     var num = someNum;
     4     var anArray = [1,2,3];
     5     var ref = someRef;
     6     return function(x) {
     7         num += x;
     8         anArray.push(num);
     9         alert('num: ' + num +
    10         '\nanArray ' + anArray.toString() +
    11         '\nref.someVar ' + ref.someVar);
    12     }
    13 }
    14 closure1=newClosure(40,{someVar:'closure 1'});
    15 closure2=newClosure(1000,{someVar:'closure 2'});
    16  
    17 closure1(5); // num:45 anArray[1,2,3,45] ref:'someVar closure1'
    18 closure2(-10);// num:990 anArray[1,2,3,990] ref:'someVar closure2'
    闭包的应用
    Singleton单例
     1 var singleton = function () {
     2     var privateVariable;
     3     function privateFunction(x) {
     4         ...privateVariable...
     5     }
     6  
     7     return {
     8         firstMethod: function (a, b) {
     9             ...privateVariable...
    10         },
    11         secondMethod: function (c) {
    12             ...privateFunction()...
    13         }
    14     };
    15 }();

    这个单例通过闭包来实现。通过闭包完成了私有的成员和方法的封装。匿名主函数返回一个对象。对象包含了两个方法,方法1可以访问私有变量,方法2访问内部私有函数。需要注意的地方是匿名主函数结束的地方的"()",如果没有这个"()"就不能产生单例。因为匿名函数只能返回唯一的对象,而且不能被其他地方调用。这个就是利用闭包产生单例的方法。

  • 相关阅读:
    bat入门--第一个bat文件
    Egret的Shape
    Less Time, More profit 最大权闭合子图(最大流最小割)
    Mayor's posters POJ
    Stars POJ
    Snacks
    有趣的数列 卡特兰数
    Devu and Flowers lucas定理+容斥原理
    整数分解为2的幂 数学
    易碎的鸟蛋 概率DP
  • 原文地址:https://www.cnblogs.com/ikuman/p/2846111.html
Copyright © 2011-2022 走看看