• 闭包及底层原理


    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]())
  • 相关阅读:
    Android手机保持屏幕常亮
    完整版在xcode打测试专用ipa包流程​
    cuda编程基础:基于cuda的简单加法和基于cuda的矩阵相加算法实现,以及对应的cpu实现对比
    我用什么笔记软件?
    ArcGIS笔记10_如何创建渔网?
    探索无界,共创未来 —来自 TDengine 的伙伴招募邀请
    农业大数据概论-按章节复习
    推荐一个stable-diffusion-webui的升级项目stable-diffusion-webui-forge
    华为云云耀云服务器L实例评测 | L实例性能测试实践
    Spring 中更加简单的存储 (五大类注解 + @bean 注解) 和读取 (属性注入 + Setter 注入 + 构造方法注入) 对象
  • 原文地址:https://blog.csdn.net/qq_34569497/article/details/133823566