提到闭包首先 要想到三点:##### 作用域 变量 函数
一 : 变量的作用域
要理解闭包就必须理解 js 中变量的作用域, 变量的作用域有俩种 : 全局变量和 局部变量
在 Javascript 语言中
函数的内部是可以读取全局变量的.
javascript 代码
- var n=888;
- function f1(){console.log(n)
- }
- f1();
函数外部是无法读取函数内部的变量的
javascript 代码
- function f1() {
- var n = 999;
- }
- alert(n); // error
注意: 函数内部声明变量的时候 一定要使用 var 命令, 如果不使用的话就是一个全局变量!
javascript 代码
- function f1(){
- n=888;
- }
- f1();
- console.log(n);//888
二: 如何从外部读取内部变量?
想要从外部读取局部变量 可以在函数内部在定义一个函数 之后 return 这个函数;
javascript 代码
- function f1(){
- var n=888;
- function f2(){
- console.log(n)
- }
- return f2;
- }
- var a=f1();
- a();//888
上面的代码中 f1 内部的所有局部变量对 f2 都是可见的, 但反过来就不对, 这就是 js 中作用域链! 子集对象会一级一级的向上寻找父极的变量.
所有父对象的变量对子集都是可见了! 反之是不成立的! 既然 f2 可以读取 f1 中的局部变量, 那么我们把 f2 作为返回值, 我们就可以从外部读取内部变量啦!
注意: f1 需要用变量保存, 如果直接执行 f1 返回的是 f2 的函数体.
三: 闭包的概念:
简单理解: 闭包就是能够读取其他函数内部变量的函数, 在本质上 闭包就是将函数内部和函数外部链接起来的一座桥梁
四: 闭包的用途:
一般的情况下 闭包有俩个作用: 1: 读取函数内部的变量 2: 让这些变量始终保存在内存中;
javascript 代码
- function f1(){
- var n=888;
- nAdd=function(){n++}
- function f2(){
- console.log(n);
- }
- return f2;
- }
- var result=f1();
- result(); // 888
- nAdd();
- result(); // 889
在上面的代码中 result 一共运行俩次 第一次值是 888 第二次值是 889 这就证明函数 f1 中的局部变量 n 是一直保存在内存中, 并没有在 f1 执行后被销毁;
这样的原因是因为: f1 是 f2 的父函数, 而 f2 被赋给了一个全局变量,(全部变量只会在关闭浏览器时会销毁)这样导致 f2 始终保证在内存中 而 f2 依赖 f1,
因此 f1 也就保存在内存中, 不会在调用结束后, 被垃圾回收机制 (garbage collection) 回收!
注意 "nAdd=function(){n+=1}" 这个代码 没有使用 var 关键字 因此是一个全局变量 其次 这个匿名函数本身就是一个闭包 所以可以在函数外部对函数内部的局部变量进行操作.
五 : 使用闭包的注意点:
由于闭包会使函数中的变量都保存在内存中, 内存消耗会很大, 内存大到一定程度就会报错, 所以不能随意使用闭包哦!
闭包练习题
javascript 代码
- var name = "The Window";
- var object = {
- name: "My Object",
- getNameFunc: function () {
- return function () {
- return this.name;
- };
- }
- };
- alert(object.getNameFunc()());
javascript 代码
- var name = "The Window";
- var object = {
- name: "My Object",
- getNameFunc: function () {
- var that = this;
- return function () {
- return that.name;
- };
- }
- };
- alert(object.getNameFunc()());
来源: http://www.qdfuns.com/note/48586/259025fc35fe286d7b456650ec18b0a4.html