JavaScript---设计模式与开发实践--第三章 闭包

JavaScript—设计模式与开发实践–第三章 闭包

  • 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。
  • 对于 JavaScript程序员来说,闭包(closure)是一个难懂又必须征服的概念。

闭包是指有权访问另一个 函数作用域中的变量的函数 ----> 《JavaScript高级程序设计》第三版

闭包就是能够读取其他函数内部变量的函数 ------阮一峰

  • 这两种解释都是易于理解的。我觉得阮一峰关于闭包的解释比较好。

总结《JavaScript—设计模式与开发实践》闭包

闭包

闭包的形成与变量的作用域以及变量的生存周期密切相关

变量的作用域

变量的作用域,指的是变量的有效范围。执行环境类型只有两种全局和局部(函数)。在函数中声明的变量就是局部变量,只有在该函数内才能访问这个变量。

        var func = function(){
           var a = 1;
           alert(a); // 1
       }
       func();
       alert(a); // a is not defined

在JS中,函数可以创造函数作用域,就好像:
此时的函数是一层半透明的玻璃,在函数里面可以看到外面的变量,而在函数外面无法看到看到函数里面的变量。

  • 变量搜索过程:在函数中搜索一个变量的时候,如果该函数内没有声明这个变量,那么此次搜索过程会随着代码执行创建的作用域链往外层逐层搜索,一直到全局对象为止。
  • 变量的搜索时从内而外而非从外到内的。
        var a = 1;
      var func1 = () => {
          var b = 2 ;
          var func2 = () => {
              var c = 3;
              alert(b);  //2
              alert(a); //1
          }
          func2();
          alert(c);  // c is not defined
      }
      func1();

变量的生存周期

除了变量的作用域之外,另外一个跟闭包有关的概念是变量的生存周期。

  • 对于全局变量来说,全局变量的生存周期是永久的,除非我们主动销毁这个全局变量。
  • 而对于在函数内用var 关键字声明的变量来说,当退出函数时,这些局部变量失去了他们的价值,他们会随着函数调用的结束而被销毁
    var func = function(){
        var a = 1;
        alert(a);
    };
    func():

退出函数(函数执行完)后局部变量a就会被销毁。
下面这个例子:

    var func = function(){
        var a = 1;
        return function(){
            a++;
            alert(a);
        }
    }
    var f = func();
    f();    //2
    f();    //3
    f();    //4
    f();    //5
  • 这里就产生了一个闭包结构。
    当退出函数后,局部变量a并没有消失,而是一直在某个地方存活着;
  • 因为当执行var f = func() 时,f 返回的时匿名函数的引用,它可以访问到func()被调用时产生的环境,而局部变量a一直在这个环境里。既然局部变量所在的环境还能被外界访问,这个局部变量就有了不被销毁的理由。这就是一个闭包结构,局部变量的声明看起来被延续了。

闭包的作用(场景)

  • 封装"私有"变量
    闭包可以帮助把一些不需要暴露在全局的变量封装成“私有变量“
            function Person() {
			var name = "asd";
			var sex = "man";
			// 这个变量是私有的变量。
			var yinsi = "....";

			return function() {
				// key: value
				var obj = {
					name: name,
					sex: sex
				}
				return obj;
			}
		}
		console.log(Person()().name);

闭包面向对象设计

下面这段代码对理解面向对象设计有很大的帮助。

    var extent = function(){
        var value = 0;
        return {
            call:function(){
                value++;
                console.log(value);
            }
        }
    };
    var e = extent();
    e.call();
    e.call();
    e.call();

把这段代码换成面向对象的写法

    var extent = {
        value : 0,
        calc  : function(){
            this.value++;
            console.log(this.value);
        }
    };
    extent.calc();
    extent.calc();
    extent.calc();

猜你喜欢

转载自blog.csdn.net/yufanhui/article/details/82924467