Javascript:没有名称的对象会怎样? [英] Javascript: What happens to objects that don't have a name?

查看:29
本文介绍了Javascript:没有名称的对象会怎样?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我(在全局范围内)执行以下操作:

If I do the following (in the global scope):

var myObject = {name: "Bob"};

我有一种方法可以指向内存中的那个对象(即字符串标识符"myObject").我可以打开控制台并键入: myObject.name ,控制台将响应:

I have a way to point to that object in memory (i.e. the string identifier "myObject)". I can open the console and type: myObject.name and the console will respond with:

"Bob"

现在,如果我只输入:

{name: "Jane"};

我正在某个地方创建该对象,并且我猜想它会继续存在于某个范围内.有什么办法可以找到它吗?它是否存在于某些通用商店中的 window 下?

I'm creating that object somewhere and I'm guessing it goes on living in some scope. Is there any way I can find it? Does it exists under window somewhere in some generic store?

有人说它将只会收集垃圾.

Some people are saying it will just get garbage collected.

那么这个例子怎么样:

var MyObject = function(){
    $("button").click(this.alert);
}

MyObject.prototype.alert = function(){
    alert("I heard that!")
}

new MyObject();

由于其回调绑定到DOM事件,因此无法进行垃圾回收.生成的对象存放在哪里,并且可以访问它?

It can't be garbage collected because its callback is bound to a DOM event. Where does the resulting object live and can it be accessed?

推荐答案

简短的回答是,对象无法在您无法访问的内存中保存.一点点的生活是活着的:如果您掌握了基本知识,事实会稍微复杂一些,但要复杂得多.

The short answer is no, the object isn't kept alive in memory somewhere you can't reach. Bit life is live: the truth is a bit more complicated, but not by much, if you grasp the basics.

更新:
回应您的更新:在某种程度上,您是对的.回调是对 MyObject.prototype.alert 的引用,您可以使用 this.alert 访问该回调,但是构造函数原型正在引用该功能对象,并且不能无论如何都要GC.实例本身不参与 alert 函数本身,因此可以安全地对其进行GC处理.

Update:
In response to your update: you're right, in a way. The callback is a reference to MyObject.prototype.alert, which you accessed using this.alert, but that function object is being referenced by a constructors prototype, and can't be GC'ed anyway. The instance itself is not involved in the alert function itself, so it can be GC'ed safely.

这样想:

MyConstructor.prototype.alert = 0x000123;//some memory address
   ||
   \/
0x000123 = [object Function];

函数对象本身没有直接附加到任何东西,它漂浮在内存中,并由原型引用.创建实例时:

The function object itself isn't directly attached to anything, it floats there in memory, and is being referenced by the prototype. When you create an instance:

new MyConstructor().alert;

解决方法如下:

[new MyConstructor instance] allocated at e.g 0x000321
   ||
   \\
    \=>[alert] check for alert @instance -> not found
          \\
           \=> check prototype, yield 0x000123 <-- memory address, return this value

因此,在执行语句后:

 $("button").click(this.alert);

this.alert 是一个解析为 0x000123 的表达式.换句话说,jQ的 click 方法(功能对象)仅接收 alert 功能对象的内存地址.实例,甚至实际上都不涉及构造函数.这就是为什么 this 或调用上下文可以根据调用函数的方式和位置进行更改的原因.请参阅此处,了解有关临时上下文确定的更多信息

this.alert is an expression that is resolved to 0x000123. In other words, jQ's click method (function object) only receives the memory address of the alert function object. The instance, or indeed the constructor isn't involved at all. That's why this, or the call-context, can change depending on how and where a function is invoked. see here for more on ad-hoc context determination

我什至会为您做一个更好的事情:

I'll even do you one better:

/*assume your code is here*/
new MyConstructor().alert = function(){ alert('I am deaf');};
MyConstructor.prototype.alert = 'foo';
$('#button').click();

猜猜是什么,点击事件警报我听说过" 都一样,原型甚至都没有涉及,更不用说实例了.
如果 MyConstructor 超出范围,则 click 事件仍将正常运行,因为GC仍会看到对警报功能对象的引用,但该引用并未超出范围然而.不过,其他所有内容都可以用于GC'ing ...

Guess what, the click event alert "I heard that" all the same, the prototype isn't even involved, let alone the instance.
If MyConstructor were to go out of scope, the click event will still work fine, because the GC still sees a reference to the alert function object that isn't out of scope yet. everything else is available for GC'ing, though...

JS垃圾收集器(GC)是标志和擦除的GC.当JS引擎遇到您的语句时,它会执行分配存储对象所需的内存.到达下一条语句时,该对象可能仍会在内存中.
GC会不时地X-检查其在内存中看到的所有对象,并尝试找到对该对象的所有引用,这些引用仍可访问.当遇到刚在该语句中创建的对象文字但未分配对它的引用时,该对象将被标记为垃圾回收.
下一次GC处理其标记对象的事务时,该对象将从内存中删除.

The JS garbage collector (GC) is a flag-and-swipe GC. When the JS engine encounters your statement, it does allocate the memory required to store your object. When the next statement is reached, that object will probably still be in memory.
Every now and then, the GC X-checks all the objects it sees in memory, and tries to locate all references to that object that are still accessible. When it comes across the object literal that was just created in that statement, but no reference to was assigned, the object is flagged for garbage collection.
The next time the GC gets about its business of swiping flagged object, that object will be removed from memory.

当然,对于所有引擎而言,这并非完全正确.假设您的语句是用IIFE编写的,并且返回了一个函数:

Of course, this isn't entirely true for all engines. suppose your statement was written in an IIFE, that returned a function:

var foo = function()
{
    {name: 'bar'};
    return function()
    {
        return 'foobar';
    };
}());

某些引擎只是将IIFE的整个范围保留在内存中,并且仅当IIFE的返回值超出范围(为GC标记)时才为该范围重新分配内存.实际上,其他引擎(例如我上次检查的V8)实际上会标记那些外部函数的返回值未引用的对象/变量.
但是,考虑一下,它可能不适用于这种情况,因为GC甚至可能在IIFE返回之前就启动了.但是,总的来说,这只是挑剔.

Some engines just keep the entire scope of the IIFE in memory, and only deallocate the memory for that scope when the return value of the IIFE goes out of scope (is flagged for GC). Other engines, like V8 last time I checked, will in fact flag those objects/vars of the outer scope that aren't referenced by its return value.
Though, come to think about it, it might not apply to this case, because the GC might even kick in even before the IIFE returns... But on the whole, that's just nit-picking.

还有逻辑或的问题要考虑:

There's also the question of logical OR's to consider:

var name = (mayNotExist || {name:'default'}).name;

在这种情况下,如果存在 mayNotExist ,则由于JS对表达式的短路求值,甚至无法创建对象文字.

In this case, if mayNotExist does exist, the object literal will never even be created, thanks to JS's short-circuit evaluation of expressions.

此事的几个链接:

这篇关于Javascript:没有名称的对象会怎样?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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