如何在Javascript中为变量分配内存? [英] How variables are allocated memory in Javascript?

查看:147
本文介绍了如何在Javascript中为变量分配内存?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道局部变量是如何在javascript中分配内存的。
在C和C ++中,局部变量存储在堆栈中。它在javascript中是一样的吗?或者一切都存储在堆中?

I would like to know how local variables are allocated memory in javascript. In C and C++ local variables are stored on stack. Is it the same in javascript? or everything is stored in heap?

推荐答案

这实际上是一个非常有趣的Javascript领域。 规范中的详细信息,但是:Javascript处理局部变量的方式与C的方式完全不同。当你调用一个函数时,除此之外还会创建一个用于该调用的变量环境,它具有一个称为绑定对象的东西。 (简称为变量对象;说变量环境的绑定对象只是一个啰嗦的 tad 位!)变量对象具有属性对于函数的参数,函数中声明的所有局部变量,以及函数内声明的所有函数(以及其他一些东西)。不合格的引用(例如 foo foo 中,而不是 obj.foo ),看它们是否匹配变量对象的属性;如果它们这样做,则使用这些属性。

It's actually a very interesting area of Javascript. Details in the spec, but: Javascript's way of handling local variables is quite different from the way C does it. When you call a function, amongst other things a "variable environment" for that call is created, which has something called a "binding object". (Call it the "variable object" for short; saying "the binding object of the variable environment" is just a tad bit long-winded!) The variable object has properties for the arguments to the function, all local variables declared in the function, and all functions declared within the function (along with a couple of other things). Unqualified references (e.g., the foo in foo, not obj.foo) within the function are first checked against the variable object to see if they match properties on it; if they do, those properties are used.

当一个闭包在函数返回时存活(由于几个原因可能发生),该函数调用的变量对象是通过闭包引用在内存中保留。乍一看,这表明堆栈不用于局部变量;实际上,现代JavaScript引擎非常智能,并且可能(如果它值得)将堆栈用于闭包实际上没有使用的本地。 (当然,堆栈仍然用于跟踪返回地址等。)

When a closure survives the function returning (which can happen for several reasons), the variable object for that function call is retained in memory by the reference from the closure. At first glance, that would suggest that the stack isn't used for local variables; in fact, modern JavaScript engines are quite smart, and may (if it's worthwhile) use the stack for locals that aren't actually used by the closure. (Naturally, the stack is still used for keeping track of return addresses and such.)

这是一个例子:

function foo(a, b) {
    var c;

    c = a + b;

    function bar(d) {
        alert("d * c = " + (d * c));
    }

    return bar;
}

var b = foo(1, 2);
b(3); // alerts "d * c = 9"

当我们打电话给 foo ,使用以下属性创建变量对象:

When we call foo, a variable object gets created with these properties:


  • a b  —函数的参数

  • c  —函数中声明的局部变量

  • bar  —在函数中声明的函数

  • (......以及其他一些事情)

  • a and b — the arguments to the function
  • c — a local variable declared in the function
  • bar — a function declared within the function
  • (...and a couple of other things)

foo 执行语句 c = a + b; 时,它引用 c a b 属性,用于调用<$ c $的变量对象C> FOO 。当 foo 返回对其中声明的 bar 函数的引用时, bar foo 的回复中幸存。由于 bar 对该特定调用 foo 的变量对象有(隐藏)引用,因此变量对象存活(而在正常情况下,它没有未完成的引用,因此可用于垃圾收集)。

When foo executes the statement c = a + b;, it's referencing the c, a, and b properties on the variable object for that call to foo. When foo returns a reference to the bar function declared inside it, bar survives the call to foo returning. Since bar has a (hidden) reference to the variable object for that specific call to foo, the variable object survives (whereas in the normal case, it would have no outstanding references and so would be available for garbage collection).

稍后,当我们调用 bar ,该调用的 new 变量对象是使用(除其他外)一个名为 d  —的属性创建的。 bar 的参数。首先根据该调用的变量对象检查 bar 中的非限定引用;例如, d 解析为变量对象上的 d 属性,用于调用。但是,对于 bar 的范围链中的下一个变量对象,检查与其变量对象上的属性不匹配的非限定引用,该变量对象是变量对象对 foo 的调用。由于它有一个属性 c ,这是中使用的属性。例如,粗略地说:

Later, when we call bar, a new variable object for that call is created with (amongst other things) a property called d — the argument to bar. Unqualified references within bar are first checked against the variable object for that call; so for instance, d resolves to the d property on the variable object for the call to bar. But an unqualified reference that doesn't match a property on its variable object is then checked against the next variable object in the "scope chain" for bar, which is the variable object for the call to foo. And since that has a property c, that's the property used within bar. E.g., in rough terms:

+----------------------------+
| `foo` call variable object |
| -------------------------- |
| a = 1                      |
| b = 2                      |
| c = 3                      |
| bar = (function)           |
+----------------------------+
             ^
             | chain
             |
+----------------------------+
| `bar` call variable object |
| -------------------------- |
| d = 3                      |
+----------------------------+

实现可以自由地使用他们想要的任何机制来使上面的看起来发生。对于函数调用,不可能直接访问变量对象,并且规范明确指出,如果变量对象只是一个概念,而不是实现的文字部分,那就完全没问题了。一个简单的实现可能只是字面上做的规范说;当没有涉及闭包时(为了速度利益),更复杂的一个可以使用堆栈,或者可以总是使用堆栈但是在弹出堆栈时撕掉闭包所需的变量对象。在任何特定情况下,唯一知道的方法是查看他们的代码。 : - )

Implementations are free to use whatever mechanism they want under the covers to make the above seem to happen. It's impossible to get direct access to the variable object for a function call, and the spec makes clear that it's perfectly fine if the variable object is just a concept, rather than a literal part of the implementation. A simple implementation may well just literally do what the spec says; a more complicated one may use a stack when there are no closures involved (for the speed benefit), or may always use a stack but then "tear off" the variable object needed for a closure when popping the stack. The only way to know in any specific case is to look at their code. :-)

更多关于闭包,范围链等的信息:

More about closures, the scope chain, etc. here:

  • Closures are not complicated
  • Poor misunderstood 'var'

这篇关于如何在Javascript中为变量分配内存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆