【问题标题】:Javascript local variable lifetimeJavascript局部变量生命周期
【发布时间】:2018-12-14 06:39:12
【问题描述】:

我精通 C、C++,但不熟悉 Javascript。我正在学习three.js,但我无法理解这里发生了什么:

var camera, scene, renderer, control;

init();

function init() {
    scene = new THREE.Scene();

    var light = new THREE.DirectionalLight( 0xffffff, 2 );
    light.position.set( 1, 1, 1 );
    scene.add( light );
}

这是我想问的简化版本。我已经阅读了很多文档和论坛,但我在任何地方都找不到。

如果我在函数内部创建“var light”并用“new”为其赋值,它将正确创建对象。由于我在函数“init”的内部声明它是局部变量。我了解到 javascript 中的对象是通过引用传递的。所以如果我通过“scene.add(light);”将它添加到场景中,为什么它仍然有效?我传递了引用,然后对象本身应该被销毁,当我在“init”之外调用渲染函数时,它应该会失败吗?

我的问题是,如果“new”关键字以某种方式使局部变量即使在函数的主体结束时仍然存在,那么在仍然存在对它的引用的情况下保持对象的活动?

我做对了吗?

【问题讨论】:

  • 对象只有在不再引用它们时才会被销毁。这就是垃圾收集的工作原理。 (您可以将其与 C++ 中的std::shared_ptr 进行比较)
  • new 并不重要。 scene.add() 可能保留对 light 的引用。
  • 如果函数一结束变量就被清除掉,那我们就麻烦了。 :)

标签: javascript three.js var


【解决方案1】:

如果我在函数内部创建“var light”并用“new”为其赋值, 它会创建对象吗?

是的。

由于我在函数“init”的内部声明它是局部变量。我了解到 javascript 中的对象是通过引用传递的。

如果您的意思是“参考”,如 C 和 C++ 参考,那么不是。如果你的意思是像Java,那么是的。有人称它为“引用副本”传递,就像传递一个指针 到对象。

所以如果我将它添加到场景中 “scene.add(light);”,为什么它仍然有效?我通过了参考,然后 对象本身应该被销毁,什么时候我会调用渲染 “init”之外的函数应该会失败吧?

对象不在栈中创建,只有指向它的值在栈中。该对象是在堆上创建的。由于您将对象传递给另一个方法,假设该方法将引用存储在某处,当您退出此函数时,该对象仍然存在。只有变量(持有“指针”)会超出范围。

我的问题是,如果“new”关键字以某种方式使局部变量 即使在函数的主体结束时仍然存在,使对象保持活动状态 虽然还有东西引用它?

当不再引用该对象时(如在 Java 中),该对象将被自动进行垃圾回收(如 C 中的 free)。

【讨论】:

    【解决方案2】:

    虽然变量light是在函数内声明的,退出后就不再存在了。变量引用的对象被“添加到场景中”scene.add(light) 并可能创建对该对象的第二个引用。一旦函数退出第一个引用 light 超出范围并删除引用,留下来自 scene.add(light) 的引用。

    JavaScript 垃圾回收只会在没有对它的引用时清理对象。

    new 除了创建一个对象的新实例之外并没有什么特别的作用。

    【讨论】:

    • 是的,我就是这么想的,太好了:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-31
    • 2011-08-06
    • 2013-02-17
    • 1970-01-01
    • 2016-12-20
    • 1970-01-01
    相关资源
    最近更新 更多