• 蓝配鸡
    2019-09-04
    希望老师再开一个专栏专门讲JS,同学们顶上去
     1
     72
  • 仰5卧0起坐
    2019-08-31
    1、从内存模型角度分析执行代码的执行流程第二步看,在堆空间创建closure(foo)对象,它是存储在foo函数的执行上下文中的。
    那么closure(foo)创建开始时是空对象,执行第三步的时候,才会逐渐把变量添加到其中。
    2、当foo函数执行结束后,foo的执行上下文是不是销毁了?如果销毁了,产生一下两个疑问:
        a、如果foo函数执行上下文销毁了,closure(foo)并没有销毁,那foo函数执行上下文是怎么销毁的呢?就比如销毁一个盒子,盒子毁里,里面的东西应该也是毁掉的
        b、既然closure(foo)既然没有销毁,那它存储在堆中的什么地方呢?必定它所依赖的foo执行上下文已经不存在了
    展开

    作者回复: 关于foo函数执行上下文销毁过程:foo函数执行结束之后,当前执行状态的指针下移到栈中的全局执行上下文的位置,foo函数的执行上下文的那块数据就挪出来,这也就是foo函数执行上下文的销毁过程,这个文中有提到,你可以参考“调用栈中切换执行上下文状态“图。

    第二个问题:innerBar返回后,含有setName和getName对象,这两个对象里面包含了堆中的closure(foo)的引用。虽然foo执行上下文销毁了,foo函数中的对closure(foo)的引用也断开了,但是setName和getName里面又重新建立起来了对closure(foo)引用。

    你可以:
    1:打开“开发者工具”
    2:在控制台执行上述代码
    3:然后选择“Memory”标签,点击"take snapshot" 获取V8的堆内存快照。
    4:然后“command+f"(mac) 或者 "ctrl+f"(win),搜索“setName”,然后你就会发现setName对象下面包含了 raw_outer_scope_info_or_feedback_metadata,对闭包的引用数据就在这里面。

     5
     43
  • 李懂
    2019-08-31
    这里讲解的真好,闭包果然不是在栈中存储的,消除了我一直以来的疑惑,上下文销毁后闭包去哪了!
    现在还有个问题,setname方法是通过什么引用闭包的,是存在内部变量么?
     1
     9
  • Marvin
    2019-08-31
    function copy(dest){
      if(typeof dest === 'object'){
        if(!dest) return dest; // null
        var obj = dest.constructor(); // Object/Array
        for(var key in dest){
          obj[key] = copy(dest[key])
        }
        return obj;
      } else {
        return dest;
      }
    }
    展开

    作者回复: 挺好 继续

     3
     8
  • 柒月
    2019-08-31
    最近面试老问这个问题,什么是深拷贝和浅拷贝以及如何实现一个深拷贝?
    1、JSON.parse(JSON.stringify(obj))
    2、递归遍历对象
    3、Object.assigin() 这种方法只能拷贝一层,有嵌套的情况就不适用了。
     3
     7
  • ChaoZzz
    2019-08-31
    1. JSON.parse(JSON.stringify(...))

    function copy(src){
        let dest;
        dest = JSON.parse(JSON.stringify(src));
        return dest;
    }
    缺点:无法拷贝函数

    2. Object.assign({}, source)

    function copy(src){
        let dest;
        dest = Object.assign({}, src);
        return dest;
    }
    缺点:只能拷贝一层

    3. function copy(src) {
        let dest;
            if (typeof src !== 'object') return ;
            dest = src instanceof Array ? [] : {};
            for (let key of Object.keys(src)) {
                dest[key] = typeof src[key] === 'object' ? deepCopy(src[key]) : src[key];
            }
            return dest;
    }
    展开
     1
     6
  • Lx
    2019-08-31
    老师,后续是否会谅解下devtools做内存分析?基本用法会,但具体分析问题不知道怎么弄……
    
     6
  • XWL
    2019-09-18
    老师,我有几个疑问:
    1、Function 函数类型也是继承于Object,声明函数后是不是也是存在堆空间中的,那么浏览器编译函数时是不是会同时创建执行上下文和向堆空间中压入一个值
    2、function a(){
                var b = 1;
                var c = {
                        d: 2
                };
         }
         当 a 的执行上下文销毁后,c 对象在堆空间中的引用会跟着销毁么,将 c 返回出去或不返回,会不会是不一样的情况
    展开

    作者回复: 函数就是一种特别的对象,所以会保存在堆上,编译函数时,这个函数的已经存在于堆中了!

    第二个问题返回了c对象的话,那么说明全局环境对c对象有引用,既然有引用那么就不会被垃圾回收器标记出来,所以c对象也就不会回收!

    
     5
  • 烈日烹雪
    2019-10-31
    老师,第二遍看时有了个疑问 字符串存在栈里,但是字符串与其他原始类型不同,不一定只占几个字节的长度。如果字符串特别长,长到好几M,也会存在栈里吗?
     1
     2
  • 浪里行舟
    2019-09-19
    老师,专栏的配图怎么画出来的

    作者回复: macos的keynote

     1
     2
  • mfist
    2019-08-31
    1. dest = JSON.parse(JSON.stringify(src))

    2. function copy(src){
      let type = typeof src
      if('object' === type){
        let result = Object.create(null)
        for(let i in src){
            if(typeof src[i] === 'object'){
              result[i] = copy(src[i])
            }else{
              result[i] = src[i]
            }
        }
        return result
      }

      return src
    }

    3. 今日总结
    javascript的内存机制主要包括数据的存放、垃圾回收、代码的执行三个部分 这一节主要介绍数据的存放,javascript作为一种动态弱类型语言(动态静态是指使用之前是否确定数据类型,强弱类型是指是否支持隐式类型转换)其在内存空间存储有三个部分:代码空间(存储可执行代码)、栈空间(存储基本数据类型)、堆空间(对象)。闭包(Closure)中的变量存放在哪里呢?内部函数引用外部函数变量时候引擎会在堆空间中创建一个closure对象存放闭包变量。
    展开
    
     2
  • 行云流水
    2019-12-25
    在看的时候有点疑惑,希望老师可以解答下:
    1. 字符串类型的值,如果很大的也是存在栈中嘛?
    2. 例如: let a = { b:1 } a.c = { d:44444444444444444 }
    定义了一个对象赋值给 a ,那么a就指向了堆内存中一段空间。在后面通过 a.c 赋值了一个很大的值。
    我的疑惑是:
    1. 原来的 a指向的空间不够用的话是怎么处理?
    2. 如果是动态添加了内存的话,原来a 保存的地址指针,还可以指向后面分配的内存嘛?
    展开
    
     1
  • Elmer
    2019-09-08
    请问从内存角度如何分析闭包是如何进行链式查找变量的。
    比如:
    function test () {
     var a = 1;
    return function () {var b=2; return function(){console.log(a,b)}}
    }
    test()()()会答应出1 2
    从内存的角度如何分析1是怎么找到的,才想闭包也有链的机制?
    展开
    
     1
  • prozac
    2020-02-10
    老师我想提个疑问,为什么存储引用类型的数据是用堆这个结构?堆的特点跟这个场景一点也不契合啊...?难道不是散列表/跳表/红黑树更适合吗
    
    
  • Sela
    2020-02-07
    function copy(src){
        let dest
        //实现拷贝代码,将src的值完整地拷贝给dest
       //在这里实现
      dest = JSON.parse(JSON.stringify(src));
        return dest
    }

    JSON.sringify 和 JSON.parse ,先将对象转换为字符串,再通过JSON.parse重新建立一个对象。
    但是这种方法的局限也很多:

    不能复制function、正则、Symbol
    循环引用报错
    相同的引用会被重复复制

    因为上面的例子知识json结构,不涉及上面3种,故可以简单处理即可。
    展开
    
    
  • 4!!
    2020-01-15
    function copy(src){
        let dest
        dest = JSON.parse(JSON.stringify(src));
        return dest
    }
    还是这个方法最方便也最全面;
    手写遍历的话要考虑的情况太多了,typeof为object的情况都要考虑,像对象、数组、函数、函数、日期、null等等
    展开
    
    
  • Tim
    2020-01-15
    原文:"弱类型 : 意味着你不需要告诉 JavaScript 引擎这个或那个变量是什么数据类型,JavaScript 引擎在运行代码的时候自己会计算出来。动态 : 意味着你可以使用同一个变量保存不同类型的数据。"

    与上文对「弱类型」、「动态」的解释正好相反了,在上文解释中提到了,一个布尔类型的变量可以被一个字符串类型变量赋值,会进行「隐式转换」,这叫做「弱类型语言」。而动态语言老师的解释是不需要定义变量是什么数据类型。
    所以老师文中对这两种概念的「总结」(也就是我评论引用的原文)弄反了,不知道理解的对不对。
    展开

    作者回复: 看来我有必要重新解释一下静态类型和动态类型,强类型和弱类型的区别了!

    要理解一门语言是静态类型还是动态类型,最本质的判断方法是看在什么时间段对类型就行检测,静态类型的语言会在编译阶段就行检测,动态类型的语言会在运行时做类型检测!

    比如C/C++是静态语言,会在编译阶段对类型就行检测,如果检测到不合法的语言,编译阶段就会报错!

    而JavaScript就是动态语言,编译阶段不会做太多类型检测,而是等到运行时再检测变量的具体类型,这是动态语言性能低于静态语言的一个关键的地方。V8对这种动态性做了大量的优化!

    要理解一门语言是弱类型还是强类型,看变量在运行时,是否能够改变类型,比如C/c++/javaScript,都可以在运行时将一种类型的变量,改成另外一种类型的,所以他们是弱类型,而JAVA就不能运行过程中修改变量类型,所以是静态语言!

    你再结合这两点看文中的内容!

    
    
  • Tim
    2020-01-13
    关于闭包的描述,如果按照老师这样理解,那么是否需要重新明确作用域查找规则呢?
    是先找词法环境 - 变量环境 - 闭包对象,还是此法环境 - 闭包对象 - 变量环境呢?

    作者回复: 其实闭包对象就是对词法作用域的一种实现

    
    
  • 尝试者说
    2019-12-14
    这门课程是我看过最好的课程,真的时候做到了深入浅出、行云流水、水银泻地般的境界。老师你多多开开前端的其他课程啊,保证很多人愿意来听课的。

    作者回复: 多谢哈,在准备V8的课程了

    
    
  • coder
    2019-12-10
    在闭包那段代码中,执行setName的时候,会不会也创建一个执行上下文?那setName执行完毕,是不是闭包就消失了(不考虑getName)?因为setName执行完毕,它的执行上下文就出栈了,那么闭包没有被引用,内存回收就清理了?
    
    
我们在线,来聊聊吧