定义:能够访问到其他函数作用域中的对象的函数,称为闭包
误区:闭包不是函数里面嵌套函数
- // 闭包写法1: 内部嵌套函数
- function fn(){
- var a = 1;
- function fn2(){
- console.log(a+1);
- }
- fn2();
- }
- fn(); //2
- // 闭包写法2:回调函数写法
- function fn(cb){
- var a = 1;
- return cb;
- }
-
- function callback(a){
- console.log(a+1);
- }
- fn(callback(2));//3
分析过程
- function books() {
- var book = '书包里面的书本'
- return function () {
- console.log(book)
- }
- }
- // 1.全局作用域中,创建books()函数前会创建一个全局对变量对象GLobal,放在Scopes中
- // 2.调用函数books()时,会先复制一份全局的GLobal对象,然后会创建一个局部作用域对象Local,然后函数作用域作为AO对象推入Local作用域顶端
- // 3.books函数执行完成后,Local作用域被销毁,只剩下Global全局作用域
- // 4.bag()函数调用时,首先会赋值一份上级books函数活动变量和全局的Global对象,然后创建一个自己的Local对象,再将自己的函数AO对象推如Local作用域链顶端
- // 5.bag()执行结束后,销毁自己的Local作用域
- var bag = books()
- bag()
1:全局对象中创建Global
2:函数books()调用时先赋值全局Global然后创建自己的Local。books()执行完成后销毁自己的Local
3:bag()调用时先复制一份books和Global的对象,然后创建自己的Local,bag调用完成后,销毁自己的Local
4.面试中常问到的问题
5.面试题
- function fn() {
- var arr = []
- for (var i = 0; i< 10; i++) {
- arr[i] = function() {
- return i
- }
- }
- return arr
- }
-
- var arr = fn()
- console.log(arr[0]())
以上代码输出10。循环时不断创建function()函数,返回i,因为var存在变量预编译,所以i最终会被覆盖为10。
解决:使用自执行函数将i放到私有作用域里面就不会被外部var的i 改变。
ES6中使用let也会有块级作用域
- function fn() {
- var arr = []
- for (var i = 0; i< 10; i++) {
- (function(i){
- arr[i] = function() {
- return i
- }
- })(i)
- }
- return arr
- }
- var arr = fn()
- console.log(arr[0]())