我的理解:
这里重点写一下 第五个例子的理解
首先要知道:闭包找到的是同一地址中父级函数中对应变量最终的值
外部函数每次执行,都会开辟一个新的空间,内部函数作用外部函数的变量都是在他对应的那个空间中
而例五的外部函数只运行了一次自然只有一个空间了,
闭包
-
闭包这个东西,当初刚接触时,听了太多了流言蜚语,导致对他有一种本能的恐惧,感觉很复杂,很不能理解,关于闭包的文章看过的数不胜数,今天用自己的想法来谈一谈闭包这个东西,希望能让大家清晰的认识闭包,
-
首先问题是什么是闭包:
- 通俗的说, 闭包是指有权访问另外一个函数作用域中的变量的函数。可以理解为(能够读取一个函数作用域的变量的函数)
- 无论通过何种手段将内部函数传递到所在的词法作用域以外,它都会持有对原始定义作用域的引用,无论在何处执行这个函数都会使用闭包。
-
其次为什么要使用闭包
-
好处
- 让外部访问函数内部变量成为可能;
- 局部变量会常驻在内存中
- 可以避免使用全局变量,防止全局变量污染
- 可以模仿块级作用域
-
坑处
- 会造成内存泄漏(有一块内存空间被长期占用,而不被释放)
- 「「闭包找到的是同一地址中父级函数中对应变量最终的值」」(在循环中的闭包函数)
- this的指向问题
-
应用场景
-
例子
-
例子1
function funA(){ var a = 10; // funA的活动对象之中; return function(){ //匿名函数的活动对象; alert(a); } } var b = funA(); b();//10 复制代码
这个例子里,调用funA里的匿名函数,他打印出了funA作用域的变量
-
例子2
function outerFn(){ var i = 0; function innerFn(){ i++; console.log(i); } return innerFn; } var inner = outerFn(); //每次外部函数执行的时候,都会开辟一块内存空间,外部函数的地址不同,都会重新创建一个新的地址 inner(); inner(); inner(); var inner2 = outerFn(); inner2(); inner2(); inner2(); //1 2 3 1 2 3 复制代码
这里外部函数每次执行,都会开辟一个新的空间,内部函数作用外部函数的变量都是在他对应的那个空间中,所以inner和inner2他们的累加都是独立的
-
例子3
var i = 0; function outerFn(){ function innnerFn(){ i++; console.log(i); } return innnerFn; } var inner1 = outerFn(); var inner2 = outerFn(); inner1(); inner2(); inner1(); inner2();//1234 复制代码
这里虽然开辟了两个独立的空间,但是i保存的是window对象上,所以他们操作的是同一个对象,所以值会累加,
-
例子4
function outerFn(){ var i = 0; function innnerFn(){ i++; console.log(i); } return innnerFn; } var inner1 = outerFn(); var inner2 = outerFn(); inner1(); inner2(); inner1(); inner2(); //1 1 2 2 复制代码
这个例子说明,独立空间的操作,和运行的顺序无关
-
例子5
(function() { var m = 0; function getM() { return m; } function seta(val) { m = val; } window.g = getM; window.f = seta; })(); f(100); console.info(g()); //100 闭包找到的是同一地址中父级函数中对应变量最终的值 复制代码
这个例子里,虽然按照顺序是getm先执行,他获得的是m=0,但是闭包里,找到的同一地址中父级函数对应变量的最终值,所以找到的是函数seta赋值后的m