javascript中的对象 [英] objects in javascript

查看:105
本文介绍了javascript中的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

原始值以javascript形式存储在堆栈中,但对象存储在堆中。我理解为什么要在堆栈中存储基元,但是对象存储在堆中的原因是什么?

Primitive values are stored in a stack in javascript but objects are stored in a heap. I understand why to store primitives in stack but any reason why objects are stored in heaps?

推荐答案

实际上,在JavaScript中甚至基元都是存储在堆中而不是存储在堆栈上(参见下面的注释下面的注释)。当控件进入函数时,将创建该函数调用的执行上下文(对象),该函数具有变量对象。所有 var 和该函数的参数(以及其他一些东西)都是该匿名变量对象的属性,与命名对象的其他属性完全相同。使用了一个调用堆栈,但规范并不要求将堆栈用于本地变量存储,并且JavaScript的闭包将使得使用堆栈a'la C,C ++等不切实际。 规范中的详细信息。

Actually, in JavaScript even primitives are stored in the heap rather than on a stack (see note below the break below, though). When control enters a function, an execution context (an object) for that call to the function is created, which has a variable object. All vars and arguments to the function (plus a couple of other things) are properties of that anonymous variable object, exactly like other properties of named objects. A call stack is used, but the spec doesn't require the stack be used for "local" variable storage, and JavaScript's closures would make using a stack a'la C, C++, etc. for that impractical. Details in the spec.

而是使用(链表)。当您引用非限定符号时,解释器会检查变量对象以查找当前执行上下文,以查看它是否具有该名称的属性。如果是这样,它会被使用;如果没有,则检查作用域链中的下一个变量对象(请注意,这是按词法顺序,不是调用顺序,如调用堆栈),依此类推,直到达到全局执行上下文为止(全局执行上下文有一个变量对象,就像任何其他执行上下文一样)。全局EC的变量对象是我们可以在代码中直接访问的唯一对象: this 在全局范围代码中指向它(以及在没有<$ c $的情况下调用的任何函数) c>显式设置此。 (在浏览器上,我们有另一种直接访问它的方法:全局变量对象有一个名为 window 的属性,用于指向自身。)

Instead, a chain (linked list) is used. When you refer to an unqualified symbol, the interpreter checks the variable object for the current execution context to see if it has a property for that name. If so, it gets used; if not, the next variable object in the scope chain is checked (note that this is in the lexical order, not the call order like a call stack), and so on until the global execution context is reached (the global execution context has a variable object just like any other execution context does). The variable object for the global EC is the only one we can directly access in code: this points to it in global scope code (and in any function called without this being explicitly set). (On browsers, we have another way of accessing it directly: The global variable object has a property called window that it uses to point to itself.)

重新提出为什么对象存储在堆中的问题:因为它们可以彼此独立地创建和释放。 C,C ++和其他使用堆栈作为局部变量的人可以这样做,因为变量可以(并且应该)在函数返回时被销毁。堆栈是一种很好的有效方法。但是对象并没有以那种直截了当的方式被摧毁;同时创建的三个对象可以具有完全不同的生命周期,因此堆栈对它们没有意义。而且由于JavaScript的本地存储在对象上,并且这些对象的生命周期(可能)与返回的函数无关......好吧,你明白了。 :-)在JavaScript中,堆栈几乎只用于返回地址。

Re your question of why objects are stored in the heap: Because they can be created and released independently of one another. C, C++, and others that use a stack for local variables can do so because variables can (and should) be destroyed when the function returns. A stack is a nice efficient way to do that. But objects aren't created an destroyed in that straightforward a way; three objects created at the same time can have radically different lifecycles, so a stack doesn't make sense for them. And since JavaScript's locals are stored on objects and those objects have a lifecycle that's (potentially) unrelated to the function returning...well, you get the idea. :-) In JavaScript, the stack is pretty much just for return addresses.

但是 ,值得注意的是,仅仅因为事情如上所述概念,这并不意味着引擎已经在引擎盖下这样做。只要它按照规范中的描述外部工作,实现(引擎)就可以自由地做他们喜欢的事情了。据我所知,V8(谷歌的JavaScript引擎,用于Chrome和其他地方)做了一些非常聪明的事情,例如使用堆栈作为局部变量(甚至是函数中的本地对象分配),然后只将它们复制到堆中。必要的(例如,因为执行上下文或其上的单个对象在通话中存活)。您可以看到,在大多数情况下,这将最大程度地减少堆碎片并且比依赖GC更积极有效地回收用于临时堆的内存,因为与大多数函数调用相关联的执行上下文不需要在调用中存活。让我们看一个例子:

However, it's worth noting that just because things are as described above conceptually, that doesn't mean that an engine has to do it that way under the hood. As long as it works externally as described in the spec, implementations (engines) are free to do what they like. I understand that V8 (Google's JavaScript engine, used in Chrome and elsewhere) does some very clever things, like for instance using the stack for local variables (and even local object allocations within the function) and then only copying those out into the heap if necessary (e.g., because the execution context or individual objects on it survive the call). You can see how in the majority of cases, this would minimize heap fragmentation and reclaim memory used for temporaries more aggressively and efficiently than relying on GC, because the execution context associated with most function calls doesn't need to survive the call. Let's look at an example:

function foo() {
    var n;

    n = someFunctionCall();
    return n * 2;
}

function bar() {
    var n;

    n = someFunction();
    setCallback(function() {
        if (n === 2) {
            doThis();
        }
        else {
            doThat();
        }
    });
}

在上面,像V8这样积极优化的引擎可以检测出概念当 foo 返回时,调用 foo 的执行上下文永远不需要存活。因此,V8可以自由地在堆栈上分配该上下文,并使用基于堆栈的机制进行清理。

In the above, an engine like V8 that aggressively optimizes can detect that the conceptual execution context for a call to foo never needs to survive when foo returns. So V8 would be free to allocate that context on the stack, and use a stack-based mechanism for cleanup.

相反,为调用<创建的执行上下文code> bar 必须在 bar 返回后继续,因为有一个闭包(我们传入的匿名函数 setCallback )依靠它。因此,在编译 bar 时(因为V8会动态编译机器代码),V8可能会使用不同的策略,实际上在堆中分配上下文对象。

In contrast, the execution context created for a call to bar has to stick around after bar returns, because there's a closure (the anonymous function we passed into setCallback) relying on it. So when compiling bar (because V8 compiles to machine code on-the-fly), V8 may well use a different strategy, actually allocating the context object in the heap.

(如果以上任何一种方式都以任何方式使用 eval ,顺便说一下,很可能是V8和其他引擎都没有甚至尝试任何形式的优化,因为 eval 引入了太多优化失败模式。另一个原因是不使用 eval 如果你不需要,而且你几乎从不需要。)

(If either of the above had used eval in any way, by the way, it's likely V8 and other engines don't even attempt any form of optimization, because eval introduces too many optimization failure modes. Yet another reason not to use eval if you don't have to, and you almost never have to.)

但这些是实现细节。 概念上,事情如上所述。

But these are implementation details. Conceptually, things are as described above the break.

这篇关于javascript中的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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