锁定老帖子 主题:Javascript 垃圾收集机制
精华帖 (0) :: 良好帖 (0) :: 新手帖 (3) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-10-15
最后修改:2011-10-15
什么是这里的“全局函数”呢?我们平时说的全局函数是指Global下提供的内置函数,但你这里说的好像不是这个意思。
|
|
返回顶楼 | |
发表时间:2011-10-15
最后修改:2011-10-15
firefly_zp 写道
变量声明是在什么地方声明的,是函数体内局部变量还是全局变量?如果是局部变量必然会有其运行环境(子函数内,闭包函数内等等),在包含此局部变量的函数运行结束后(变量 a 没有被其他变量引用),就会被释放。如果是全局变量,当包含这个全局变量的函数体运行结束后,这个变量才会被释放,否则一直在环境内,不会释放的。
单说 a = 1 这个函数声明(如果只有这一行,那就不是 js 了。他必然包含在某个函数中 - 或全局函数或内部函数),a = 1 执行完成后是“进入环境”,因为他被包含于某个函数中,当他被包含于的这个函数执行结束后,并且没有其他变量对他的引用时,这个时候的状态才是“离开环境”。
我们现在所说的“离开环境”的状态主要有两点:第一,变量本身离开其所处的环境(最直接的可以看出)。第二,如果变量被其他变量所引用,则要去判断引用 a 的变量是否离开了他的环境,如果两点都符合,则此时的 a = 1的状态是“离开环境”。
a = 1; 这个是函数? 不是JS? JS难道规定了要成为JS,必须要多少代码,必须要有函数?
我晕,变量定义而已。 这个变量成了全局对象的一个property。 这个环境是the global object, 不是什么函数!!!
In top-level JavaScript code (i.e., code not contained within any function definitions),
|
|
返回顶楼 | |
发表时间:2011-10-15
最后修改:2011-10-15
to firefly_zp:
你说的“离开环境”、“进入环境”其实就是指能不能被访问到,这就是标记法的核心:将所有能访问到的对象都标记,剩下未被标记的就是永远不可能被访问到的,可以随意清除。它能有效清理不能访问的循环引用,但缺点是遍历所有对象成本可能有些高。 本来就不必再引入“环境”这个概念,你说的判断条件也是有问题,比如以下的Date对象就没有变量引用它,但它也不会被释放: function closure(){ var a = new Date(); return function(){}; } var ref = closure(); 它实际的引用路线是: ref -> 返回的匿名函数 返回的匿名函数.[[scope]] -> (scope closure 1) (scope closure 1).a -> Date object 1 P.S. 这里虽然Date object 1在我们的程序中是无法访问到的,但标记法不会去判断内部匿名函数是不是真的没有代码去访问,它只是判断内部匿名函数记录定义时的scope chain引用到了那层scope,scope上有个属性引用到了Date对象。 |
|
返回顶楼 | |
发表时间:2011-10-15
clue 写道 你说的“离开环境”、“进入环境”其实就是指能不能被访问到,这就是标记法的核心:将所有能访问到的对象都标记,剩下未被标记的就是永远不可能被访问到的,可以随意清除。它能有效清理不能访问的循环引用,但缺点是遍历所有对象成本可能有些高。
本来就不必再引入“环境”这个概念,你说的判断条件也是有问题,比如以下的Date对象就没有变量引用它,但它也不会被释放: function closure(){ var a = new Date(); return function(){}; } var ref = closure(); 它实际的引用路线是: ref -> 返回的匿名函数 返回的匿名函数.[[scope]] -> (scope closure 1) (scope closure 1).a -> Date object 1 P.S. 这里虽然Date object 1在我们的程序中是无法访问到的,但标记法不会去判断内部匿名函数是不是真的没有代码去访问,它只是判断内部匿名函数记录定义时的scope chain引用到了那层scope,scope上有个属性引用到了Date对象。 看我上面引用的那段话。 But if the function defines a nested function and returns it or stores it into a property somewhere, then there will be an external reference to the nested function. It won’t be garbage collected, and the variable binding object it refers to won’t be garbage collected either |
|
返回顶楼 | |
发表时间:2011-10-15
最后修改:2011-10-15
In order to implement lexical scoping, the internal state of a JavaScript function object must include not only the code of the function but also a reference to the current scope chain.
var scope = "global scope"; // A global variable function checkscope() { var scope = "local scope"; // A local variable function f() { return scope; } // Return the value in scope here return f(); } checkscope() // => "local scope" var scope = "global scope"; // A global variable function checkscope() { var scope = "local scope"; // A local variable function f() { return scope; } // Return the value in scope here return f; } checkscope()() // => "local scope" var scope = "global scope"; // A global variable function checkscope() { var scope = "local scope"; // A local variable function f() { var scope = "nested scope"; return scope; } return f; } checkscope()() // => "nested scope" |
|
返回顶楼 | |
发表时间:2011-10-15
psychopath 写道 看我上面引用的那段话。 But if the function defines a nested function and returns it or stores it into a property somewhere, then there will be an external reference to the nested function. It won’t be garbage collected, and the variable binding object it refers to won’t be garbage collected either 我前面的回复是对楼主说的,是因为我觉得没有必要为了解释一件本来比较简单的事情引入一个更复杂的概念。 你这段话也是scope chain、[[scope]]、以及标记回收法实现后的效果 P.S. JS的规则其实很简单,只不过不像C、Java那样有专门的课程教我们,所以大家都偏向野路子:对一个机制各有各的说法,并且很多时候都不了解更深层的原理。 这是因为我们很多JS方面的知识不是通过JS标准(ECMAScript)来由下向上得到,而是从网络上各个大牛们的总结得出印象、自上向下慢慢深入的。这样有个缺点,就是知识很零散、片面,并且感觉关联不强,但真正参考ECMAScript文档才发现它们其实都是某些机制导致的必然结果。 |
|
返回顶楼 | |
发表时间:2011-10-15
clue 写道 P.S.
JS的规则其实很简单,只不过不像C、Java那样有专门的课程教我们,所以大家都偏向野路子:对一个机制各有各的说法,并且很多时候都不了解更深层的原理。 这是因为我们很多JS方面的知识不是通过JS标准(ECMAScript)来由下向上得到,而是从网络上各个大牛们的总结得出印象、自上向下慢慢深入的。这样有个缺点,就是知识很零散、片面,并且感觉关联不强,但真正参考ECMAScript文档才发现它们其实都是某些机制导致的必然结果。 JS的规则其实很简单,这个我不大苟同。 C我的基础应该还算可以的,但是我觉得C的规则是很清晰明了的。 但是自从学了这个JavaScript后,发现它的规则多的是,而且有很多例外,ES3 和 ES5C差别大了,还是 严格模式还有非严格模式。 说实话,我看楼主中文的表述还是比较晕的,很多概念都没看到过,可能翻译不同吧,就连你说的什么active object我还没看到呢,呵呵,虽然看英文有些吃力,但是感觉真正能学得到东西。 |
|
返回顶楼 | |
发表时间:2011-10-15
实际操作中总结起来就一句话: 杜绝循环引用。但如何杜绝在ie中是很有学问的,比如在闭包中的事件注册。
|
|
返回顶楼 | |
发表时间:2011-10-15
JS真的不简单,给大家出个题,最后输出啥
var scope = "testing"; function test() { var scope = "global"; return function() { var scope = "local"; return new Function("return scope"); } } test()()(); |
|
返回顶楼 | |
发表时间:2011-10-15
psychopath 写道 JS的规则其实很简单,这个我不大苟同。 C我的基础应该还算可以的,但是我觉得C的规则是很清晰明了的。 但是自从学了这个JavaScript后,发现它的规则多的是,而且有很多例外,ES3 和 ES5C差别大了,还是 严格模式还有非严格模式。 说实话,我看楼主中文的表述还是比较晕的,很多概念都没看到过,可能翻译不同吧,就连你说的什么active object我还没看到呢,呵呵,虽然看英文有些吃力,但是感觉真正能学得到东西。 C并不简单,主要语法看起来没啥,但边边角角的东西太多太多,我就被好些问题恶心到过,比如内存对齐、线程同步、各种宏啊指针转换啊等等 知道公认的开发效率比较吧? JS > Java > C。当然,这是在每语言都掌握了的情况下。(这也是NodeJs为什么兴起) JS有时是有很多例外,但都是些非必需的,比如eval、new Function等,实际开发中几乎根本用不到。真正重要的就只有那几点: 函数定义 函数执行(变量初始化、执行顺序等) new创建(原型链) 这些弄懂了,最大头的啥原型链、闭包什么的都是秒杀,而这些内容在ECMAScript文档中总共也就几页纸而已。 前端JS开发其实并不是难在JS语法及特性上,而是浏览器环境上(DOM、CSS、浏览器差异),东西太多太杂。当然目前有了JS框架后改善了很多。 信不信如果大学开JS课程,那Web前端开发绝对不会缺成这样子。 |
|
返回顶楼 | |