【问题标题】:correctly resetting a global variable in javascript?在javascript中正确重置全局变量?
【发布时间】:2013-04-18 16:23:47
【问题描述】:

所以,在 this post here,人们正在讨论一个事实,即

A = [1,2,3];

然后做

A = [];

不会重置数组而是创建一个新数组。

我的问题是,如果我使用全局对象变量

myglobals = { A : [] }

我可以安全地重置数组吗

myglobals.A = [];

对吗?因为这引用了相同的对象属性,因此我实际上并没有创建一个新数组,是吗?

由于以下评论而更新问题

由于人们普遍认为splice(0) 是可行的方法,并且由于一个非常相似的问题的答案解释了对浏览器释放内存的影响,所以我想知道设置它是否通常是安全和适当的任何已定义的对象(无论是数组、函数还是字符串等)到null,以便在保留它的引用的同时重置它的

【问题讨论】:

  • 一个对象仍然可以有它的原型,而且它必须!这就是javascript。原型对象,无论是否为空!因为即使null 是东西,它什么都不是,所以[] 也是东西,但是var A=undefined 是未定义的,但是作为某些原型/类型的对象存在!
  • @alex23,感谢您提及其他帖子。看来myglobals.A.splice(0) 实际上并不是最好的方法。从那里接受的答案中,我了解到它应该设置为 null 以允许浏览器收集内存,对吧?
  • @codelio,也许我没有很好地问我的问题,如果是这样的话,我很抱歉。你下面的答案听起来不对:如果我设置A=undefined,那么typeof(A) 返回undefined 但我希望得到object
  • null 没有准备 A 释放其占用的内存,因为它为空。看看var A=1; A=void(A),也许这就是你的意思,但它仍然是有效的A,就像var A在这一刻一样。如果设置了 objects/value 的父级以使其不再具有该子级,则 javascript 会释放内存。
  • console.log(a.constructor.name, typeof a); //"数组", "对象"

标签: javascript arrays variables scope


【解决方案1】:
var handle={};
handle.A=[1,2,3,4,5,{x:2,y:3}];
console.log(handle);

delete handle.A;
console.log(handle); //A is gone!

为什么有时删除更好?它真的会从handle 杀死A,如果您希望.length 告诉您真相,以下可能会使您在处理更大的对象时感到困惑。

handle.A=[null];
handle.B=undefined;
handle.C=null;
handle.A.length=10;
console.log(handle, handle.length, handle.A.length);

不是很节省编码,因为我将它设置为=10 和 您的脚本可能会假设错误,有一些东西要循环通过 10 个元素。 所以handle.A=null 会有所帮助,但不会真正改变对象的结构。 但它也不能破坏你的脚本,因为你有类似var A 的东西,你可以防止循环通过不存在的元素。同样适用于设置为undefined,见下文..

【讨论】:

  • 在这种类型的打字中你真的可以为 A 释放内存
【解决方案2】:
var A=[1,2,3];
A=undefined;
console.log(A); //undefined

【讨论】:

  • 嗯,现在只是将数组更改为空,而不是将其重置为array 类型的变量。我想这样我可以做两个陈述:A=undefined;A=[]; 但这确实删除了 A 分配还是只是添加了一个新的引用? A=null 怎么样?
  • 任何覆盖变量都可以。 A.length=0 不会在任何时候起作用,取决于 A 的类型。换句话说,它是由什么样的原型制成的。但是用低级类型覆盖总是会清空其中的所有内容,特别是在使用它更改类型时,nullundefined 会做什么!
  • 换句话说,一旦给定一个变量,它就有一个作用域!它所属的某个地方。但是,如果它所属的内容被更改或覆盖,则 javascript 将释放新事物的空间.. 就像写 var A 一样,但不是什么都没有,它是未定义的!
【解决方案3】:

不是真的……

// make a global variable
var a = [1,2,3];

// Assign it to something
var someObj = { value: a };
someObj.value; // [1,2,3];

// set a new value for the global
a = [];
a; // []
someObj.value; // [1,2,3];

这是您提到的初始代码。您可以更改全局变量指向的对象,但不能更改对要替换的对象的其他引用。

你的第二个例子也存在同样的问题:

// make a global variable
var globals = { a: [1,2,3] };

// Assign it to something
var someObj = { value: globals.a };
someObj.value; // [1,2,3];

// set a new value for the global
globals.a = [];
globals.a; // []
someObj.value; // [1,2,3];

如果要更新引用,则必须引用 globals 容器对象。即其他对象持有对容器的引用,然后您可以更改该容器的内容。

// make a global variable
var globals = { a: [1,2,3] };

// assign a reference to the container in another object.
var someObj = { globals: globals };
someObj.globals.a; // [1,2,3];

// set a new value for the global
globals.a = [];
globals.a; // []
someObj.globals.a; // [];

这可能会有点笨拙。


您还可以通过全局更改对象引用,而不是替换它。

var a = [1,2,3];
var b = a; // a and b now reference the same object.

a.splice(0); // remove all items from this array, without replace the array object.
a; // [];
b; // [];
// a and b now still point to the same array, which is now empty.

【讨论】:

  • 我想应该是a.splice(0)在最后。
【解决方案4】:

您正在创建一个新数组。如果要截断数组,只需将其长度设置为零:

var a = [1,2,3];
a.length = 0;
// a is now []

在您的带有对象属性的示例中,它是一样的。 JavaScript 中没有指针,只有引用值。所以myglobals.A 的值是对数组的引用。当您为其分配一个新数组时,该值将成为另一个数组的新引用。

【讨论】:

  • 要清空一个数组,需要移除对象上的所有元素(设置arr.length = 0实际上不会从数组中移除引用),合理清空数组的简洁方法是: arr.splice(0).
  • @zzzzBov 你确定吗?因为var a = [1,2,3]; a.length = 0; a[1]; // undefined.
  • arr.splice(0) 会影响当前的数组引用(也许你在想arr.slice,这是类似的),但看起来你对a.length = 0 清除数组项是正确的。我的印象是它只是掩盖了数组实例上属性的存在。
  • 所以如果它应该是myglobals.A.splice(0),如果我的变量是一个对象,我该怎么做?我是myglobals.A=undefined吗?如下所示?
  • @zzzzBov 是的,我读了“splice”并想到了“slice”,然后意识到了错误。关于将长度设置为零,该规范包括一个特殊的数组内部方法来处理长度变化,请参阅es5.github.io/#x15.4.5.1
【解决方案5】:

不,这仍然会创建一个新数组。重要的因素是赋值,而不是“A”变量所附加的范围。只要您执行类似于something = [] 的操作,JavaScript 引擎就会制造一个新的 Array 对象([] 部分),然后将其引用分配给something

【讨论】:

    猜你喜欢
    • 2016-04-05
    • 1970-01-01
    • 2014-04-24
    • 2017-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多