• 闭包及底层原理


    1.闭包概念

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

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

    2.闭包的两种写法

    2.1函数嵌套写法

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

    2.2回调函数写法

    1. // 闭包写法2:回调函数写法
    2. function fn(cb){
    3. var a = 1;
    4. return cb;
    5. }
    6. function callback(a){
    7. console.log(a+1);
    8. }
    9. fn(callback(2));//3

    3.完整示例及分析

    分析过程

    • 1. 全局执行上下文创建作用域链,作用域链包含了全局变量对象 [作用域链:[全局变量对象]]
    • 2. books函数调用时创建作用域链,具体操作为先复制全局的作用域,然后创建活动对象AO推入当前作用域的顶端 [作用域链:[book活动变量, 全局变量对象]],books函数执行完毕后当前作用域会被销毁
    • 3. bag函数调用创建作用域,首先复制上层作用域[作用域链:[book活动变量, 全局变量对象]],然后创建活动对象AO推入当前作用域的顶端[作用域链:[匿名函数func, book活动变量, 全局变量对象]],bag函数执行完毕后当前作用域会被销毁
    1. function books() {
    2. var book = '书包里面的书本'
    3. return function () {
    4. console.log(book)
    5. }
    6. }
    7. // 1.全局作用域中,创建books()函数前会创建一个全局对变量对象GLobal,放在Scopes中
    8. // 2.调用函数books()时,会先复制一份全局的GLobal对象,然后会创建一个局部作用域对象Local,然后函数作用域作为AO对象推入Local作用域顶端
    9. // 3.books函数执行完成后,Local作用域被销毁,只剩下Global全局作用域
    10. // 4.bag()函数调用时,首先会赋值一份上级books函数活动变量和全局的Global对象,然后创建一个自己的Local对象,再将自己的函数AO对象推如Local作用域链顶端
    11. // 5.bag()执行结束后,销毁自己的Local作用域
    12. var bag = books()
    13. bag()

    1:全局对象中创建Global

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

     

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

     

    4.面试中常问到的问题

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

    5.面试题

    1. function fn() {
    2. var arr = []
    3. for (var i = 0; i< 10; i++) {
    4. arr[i] = function() {
    5. return i
    6. }
    7. }
    8. return arr
    9. }
    10. var arr = fn()
    11. console.log(arr[0]())

     以上代码输出10。循环时不断创建function()函数,返回i,因为var存在变量预编译,所以i最终会被覆盖为10。

    解决:使用自执行函数将i放到私有作用域里面就不会被外部var的i 改变。

    ES6中使用let也会有块级作用域

    1. function fn() {
    2. var arr = []
    3. for (var i = 0; i< 10; i++) {
    4. (function(i){
    5. arr[i] = function() {
    6. return i
    7. }
    8. })(i)
    9. }
    10. return arr
    11. }
    12. var arr = fn()
    13. console.log(arr[0]())
  • 相关阅读:
    【JAVA刷题初阶】刷爆力扣第十一弹——二叉树
    如何重置iPhone的网络设置?这里提供详细步骤
    车载语音识别系统语音数据采集标注案例
    周年纪念篇
    AWS的RDS数据库开启慢查询日志
    python3.6环境下安装gevent,附协程TCP服务器客户端代码
    java--拼图游戏
    区块链国际会议汇总
    基于Springboot+Vue的Java项目-家政服务平台系统开发实战(附演示视频+源码+LW)
    大数据学习笔记1.3 Linux用户操作
  • 原文地址:https://blog.csdn.net/qq_34569497/article/details/133823566