function myClass()
{
//lots and lots of vars and code here.
this.bar = function()
{
//do something with the numerous enclosed myClass vars
}
this.foo = function()
{
alert('Hello'); //don't do anything with the enclosed variables.
}
}
myClass的每个实例都有自己的bar和foo副本,这就是原型方法使用更少内存的原因。但是,我想更多地了解内部方法的内存使用。
我觉得以下(1)必须是真的。你同意吗?
现在(2)是我真正追求的问题。
答案 0 :(得分:1)
我有理由确定任何函数都有一个指向整个状态的指针。它是否引用它仍然可以访问它们的任何变量是无关紧要的。
当然你确实发布了bar& amp; foo指向对象的相同“整个状态”。所以它不需要更多的内存。我猜你必须在内部再分配一个指针,这样你就可以指向对象的“整个状态”,但是对于类似的东西进行优化是很愚蠢的。
是否优化它是特定于javascript引擎。一定要读取铬源并找出答案。
我会看看我是否可以为你挖出一些报价。
输入规范中的功能代码:
10.4.3输入功能代码执行以下步骤时 控制进入执行上下文 用于包含的功能代码 函数对象F,提供的调用者 thisArg和调用者提供的 argumentsList:
- 如果功能代码是严格代码,请将ThisBinding设置为thisArg。
- 否则,如果thisArg为null或未定义,则将ThisBinding设置为 全球对象。
- 否则如果Type(thisArg)不是Object,则将ThisBinding设置为 ToObject(thisArg)。
- 否则将ThisBinding设置为thisArg。
- 让localEnv成为调用NewDeclarativeEnvironment的结果 传递[[Scope]]的值 F的内部属性为 论点。
- 将LexicalEnvironment设置为localEnv。
- 将VariableEnvironment设置为localEnv。
醇>
将您的环境跟踪到NewDeclarativeEnvironment。
<强> NewDeclarativeEnvironment 强>
10.2.2.2 NewDeclarativeEnvironment(E)抽象操作时 调用NewDeclarativeEnvironment 无论是词汇环境还是 null作为参数E以下步骤 执行:
- 让我们成为一个新的词汇环境。
- 让envRec成为一个包含no的新声明性环境记录 绑定。
- 将env的环境记录设置为envRec。
- 将env的外部词法环境参考设置为E.
- 返回环境
醇>
这会将您的环境跟踪到E,它是函数Object
的[[Scope]]
13.2创建函数对象给定指定的可选参数列表 通过FormalParameterList,一个正文 由一个Lexical的FunctionBody指定 Scope指定的环境,和 布尔标志Strict,一个Function对象 构造如下:
- 创建一个新的本机ECMAScript对象,让F成为该对象。
- 如上所述设置F的[[Get]]除外的所有内部方法 在8.12。
- 将F的[[Class]]内部属性设置为“Function”。
- 将F的[[Prototype]]内部属性设置为标准内置属性 指定的函数原型对象 在15.3.3.1中。
- 按照15.3.5.4中的说明设置F的[[Get]]内部属性。
- 按照13.2.1中的说明设置F的[[Call]]内部属性。
- 按照13.2.2中的说明设置F的[[Construct]]内部属性。
- 按照中所述设置F的[[HasInstance]]内部属性 15.3.5.3。
- 将F的[[Scope]]内部属性设置为Scope的值。
- 让名称成为包含从左到右文字或
的列表 醇>
转出规格只是告诉你已经知道的事情。每个函数都包含Scope。正如另一张海报所提到的那样,在内存管理方面,“优化”某些范围取决于个人实施。
如果你问我,你真的不关心这个,除非你有>百万个这些对象的实例。
规范中的以下块更适用:
外部环境参考是 用于建模的逻辑嵌套 词汇环境价值观。外面的 (内部)词汇的引用 环境是对的参考 逻辑上的词汇环境 围绕着内心的词汇 环境。一个外在的词汇 当然,环境可能有它的 拥有外在的词汇环境。一个 词汇环境可以作为 多重内在的外部环境 词汇环境。例如,如果 FunctionDeclaration包含两个 嵌套的FunctionDeclarations然后 每个词的词汇环境 嵌套函数将作为他们的 外部词汇环境词汇 当前执行的环境 周围的功能。
两个嵌套函数对外部Lexical Environment
答案 1 :(得分:1)
这完全取决于实施而非语言。朴素的实施将远远超过其他实施。任何答案都适用于例如V8(chrome的JS引擎)可能不适用于Spidermonkey(Firefox)或JScript(IE)等......
根据我的经验(这肯定是GHC处理闭包的方式),函数(内部或外部)的实际代码只存在一次,但必须保留将值映射到值的“环境”关闭(bar),所以不,我不希望JS实现保留MyClass的多个副本,但它将保留其环境的副本至少与this.bar
,合理的实现可能意识到实际上不需要任何环境foo
实际上并不是一个闭包,因此不需要在调用MyClass
时保留环境的副本,但是不要依靠这种行为。
特别是因为JS的eval
函数的行为在与eval
调用相同的词汇环境中计算字符串,所以很有可能JS实现总是保持周围的词汇环境。
答案 2 :(得分:1)
好吧,让我们问一些实施他们做了什么,我们应该: - )
Spidermonkey: Internals-Functions - 同意其他答案。谈谈如何对封闭进行分类。
V8: Are Closures Optimized - 非常简洁,但确实提到了“静态优化”。网上的各种文章谈论“隐藏类”,我相信,是V8 GC尝试优化闭包的方式。
可悲的是,那些微薄的链接是我所能找到的。可能需要直接分析引擎源代码以添加更有意义的输入。
所以,是的,不同的引擎做时可以实现不同的优化策略。