闭包及底层原理

1.闭包概念

定义:能够访问到其他函数作用域中的对象的函数,称为闭包

误区:闭包不是函数里面嵌套函数

2.闭包的两种写法

2.1函数嵌套写法

        // 闭包写法1: 内部嵌套函数
        function fn(){
            var a = 1;
            function fn2(){
                console.log(a+1);
            }
            fn2();
        }
        fn(); //2

2.2回调函数写法

    // 闭包写法2:回调函数写法 
        function fn(cb){
            var a = 1;
            return cb;
        }

        function callback(a){
            console.log(a+1);
        }
        fn(callback(2));//3

3.完整示例及分析

分析过程

  • 1. 全局执行上下文创建作用域链,作用域链包含了全局变量对象 [作用域链:[全局变量对象]]
  • 2. books函数调用时创建作用域链,具体操作为先复制全局的作用域,然后创建活动对象AO推入当前作用域的顶端 [作用域链:[book活动变量, 全局变量对象]],books函数执行完毕后当前作用域会被销毁
  • 3. bag函数调用创建作用域,首先复制上层作用域[作用域链:[book活动变量, 全局变量对象]],然后创建活动对象AO推入当前作用域的顶端[作用域链:[匿名函数func, book活动变量, 全局变量对象]],bag函数执行完毕后当前作用域会被销毁
        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

闭包及底层原理_第1张图片

2:函数books()调用时先赋值全局Global然后创建自己的Local。books()执行完成后销毁自己的Local

闭包及底层原理_第2张图片 

3:bag()调用时先复制一份books和Global的对象,然后创建自己的Local,bag调用完成后,销毁自己的Local

闭包及底层原理_第3张图片 

4.面试中常问到的问题

  • 1.如何在外部访问函数作用域内的变量,请手写一段代码进行验证
  • 2.闭包为什么会造成内存的泄露 (内存泄漏在哪个环节有问题)

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]())

你可能感兴趣的:(JS高级,闭包及底层原理)