js 闭包的理解

Javascript语言特有的”链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。父对象的所有变量,对子对象都是可见的,反之则不成立。

应用背景:
1)有时候需要得到函数内的局部变量,那就是在函数的内部再定义一个函数。
2)让变量的值始终保持在内存中。

一、闭包的概念:

个人理解:闭包就是能够读取其他函数内部变量的函数。由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成”定义在一个函数内部的函数”。
所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

function w(){
    var c = "开创独立王国的闭包";
    var n = 1;
    function b() {
        console.log(c+'----打印'+n+'次');
        n++;
    }
    return b;
}
var f1 = w()

f1()//开创独立王国的闭包----打印1次
f1()//开创独立王国的闭包----打印2次

官方对闭包的定义:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。

结合以上示例,分析官方定义:
1、环境的表达式(通常是一个函数)—指的是函数b;
2、b拥有很多变量:c、n…;
3、b绑定了这些变量,比如b绑定了n;每次通过f1执行完b后,b的执行上下文n不消失,可以每次叠加。
4、这些变量也是该表达式的一部分:c、n确实是b函数的一部分。

闭包的意义在于:
1)js有两个作用域:全局作用域,函数的局部作用域;
2)局部作用域内可以访问全局作用域,但是全局作用域内却无法访问局部作用域。

二、闭包的特点:

1)可以访问父级函数的变量;
2)闭包函数内的this指向window;

var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      return function(){
        return this.name;
      };
    }
  };
  alert(object.getNameFunc()());//The Window

3)不能直接访问父级函数的this和arguments;
闭包函数,也是一个内部函数,内部函数不能直接访问父级函数的this和arguments;可以通过在父级函数内将this和arguments赋值给变量,再通过访问父级函数变量的方式访问。

//不能直接访问父级函数的this
var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      return function(){
        return this.name;
      };
    }
  };
  alert(object.getNameFunc()());//The Window
//将父级函数的this赋值给that变量,通过that访问父级函数的this
var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      var that = this;
      return function(){
        return that.name;
      };
    }
  };
  alert(object.getNameFunc()());//My Object

4)闭包函数使用的变量会被存入内存;
闭包函数所产生的上下文环境中包含的变量会被存入内存,不会随调用结束而被销毁,只有刷新或关闭浏览器才销毁。

三、案例:

难点闭包示例:

function w(){
    var c = 8;
    console.log("w被执行了")
    function b() {
        console.log(c);
        c++;
    }
    return b;
}
console.log(w());
// b() {
//         console.log(c);
//         c++;
//     }
w()()//8 每次调用的时都是重新定义c
w()()//8
w()()//8
var d = w();//d是指向window,把w存储在window下
d()//8  每次调用时,只是对定义在内存当中的c进行改变
d()//9
d()//10
console.log(c) //undefined c被存储起来,但是c不是在window下(重点不太好理解) 

原因:d是创建国家d后,特工d多次执行命令的过程,因此对原来的国家d的变量改变是叠加的;w()()实际上时不断地创建新国家和新特工;

四、深探闭包:

整个js程序是最大的函数,程序一旦执行,就会产生一个全局的上下文,只要程序处于执行中,这个全局上下文永远不会消失,直至结束整个程序。

五、结语:

1、闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量。由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2、不必纠结到底怎样才算闭包,其实你写的每一个函数都算作闭包,即使是全局函数,你访问函数外部的全局变量时,就是闭包
的体现。

参考:
作者 ybdt1201
地址 https://blog.csdn.net/ybdt1201/article/details/53366613
作者 ruanhongbiao
https://blog.csdn.net/qappleh/article/details/80320476

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值