Javascript 使用';var';在已经存在的变量上
假设我为代码中的Javascript 使用';var';在已经存在的变量上,javascript,memory,memory-management,Javascript,Memory,Memory Management,假设我为代码中的对象启动了var var base={x:Infinity,y:Infinity} 后来我也在同一个范围内 var base={x:0,y:0} 我知道我可以重复使用现有的变量,但我试图在一个点上迭代 就内存而言,这是否会导致当前作用域出现任何问题 如果这些在不同的范围内,会有什么问题吗 对于已经存在的变量,一般的规则是永远不要使用var吗 如果我这样做了好几次(数千次),我会遇到任何“古怪”的问题吗 它释放对旧值的保留,因此可能会对其进行垃圾收集。我说可能,因为对象可以被不同的
对象启动了var
var base={x:Infinity,y:Infinity}代码>
后来我也在同一个范围内
var base={x:0,y:0}
我知道我可以重复使用现有的变量,但我试图在一个点上迭代
就内存而言,这是否会导致当前作用域出现任何问题
如果这些在不同的范围内,会有什么问题吗
对于已经存在的变量,一般的规则是永远不要使用var吗
如果我这样做了好几次(数千次),我会遇到任何“古怪”的问题吗
它释放对旧值的保留,因此可能会对其进行垃圾收集。我说可能,因为对象可以被不同的变量引用
如果它们在不同的作用域中,则内部的基
将覆盖外部的(假设您谈论的是嵌套的作用域),因此旧值不会被覆盖。通常最好避免阴影
一般来说,在相同的范围内,是的,但这更多的是一种编码风格。它不会对执行产生有效的影响,因为无论在同一范围内声明相同的var
多少次,只有一个声明
视情况而定。你是说在循环中覆盖吗?如果您不再需要当前值,那么它不应该是一个问题
明确地说,当您执行此操作时:
var base = {x:Infinity, y:Infinity};
var base = {x:0, y:0}
真正发生的是:
var base; // declaration is hoisted
base = {x:Infinity, y:Infinity}; // new object is referenced by base
base = {x:0, y:0} // previous object is released, and new object is referenced
请注意,当我谈论范围和var
时,我是专门谈论函数范围的。在标准JavaScript/ECMAScript实现中,没有块作用域,因此在for
语句中使用var
时没有特殊意义
正如所提到的,Mozilla有let
,它确实允许在块中进行范围界定,但它需要特定的关键字。var
语句无法识别与变量范围有关的块。这样做绝对没有问题。毕竟,在函数(-context)中声明的变量只不过是被称为激活对象的一部分(ES edition 3)。在ES5中有点不同,但这一部分基本相同
您只是在覆盖对象(不是Javascript对象,而是来自底层js引擎)中的属性
因此,这一点也不是问题(即使它的不同寻常之处看起来令人困惑)
如果您在另一个“范围”(这里基本上是指另一个函数)中声明一个变量,也没有问题。每个(执行)上下文完全独立,不能与另一个上下文相互干扰,除非我们讨论的是闭包之类的东西。但即使如此,如果有多个函数和父上下文都具有相同的命名变量,则查找过程(名称解析)始终从本地范围(当前上下文中的激活对象)开始,然后进入“范围链”
我想答案应该是3)和4。)。您“可以”对变量进行var,但这毫无意义。所以我建议不要再这样做了
var关键字为变量提供作用域。此时JavaScript唯一可用的作用域是函数作用域。如果变量的作用域已限定到此函数,则再次使用var关键字进行设置不会产生任何效果
JavaScript是lambda语言,这意味着在更高范围内声明的变量可用于该更高范围内的函数。在较低的函数作用域中使用var关键字从较高的作用域提供变量可能是有害的,因为您现在已经创建了一个局部变量,该局部变量可以用作闭包。考虑下面两个例子:
var a = function () {
var b = 3,
c = function () {
var d = 5;
b = 5;
return d + b; // this is 10
};
return c() + b; // this is 10 + 5, or 15
};
var a = function () {
var b = 3,
c = function () {
var b = 5,
d = 5;
return d + b; // this is 10
};
return c() + b; // this is 10 + 3, or 13
};
我说过无意中改变变量范围可能是有害的,因为它会混淆代码的工作方式和您认为它应该如何工作 一般规则是每个函数有一个var
声明,并且var
声明位于函数的顶部:
function foo() {
var bar;
}
这样做的原因是为了避免因变量提升而引起的混乱
其中一个重要的例子是回调的闭包上下文:
//this looks like it will count up, but it wont
function foo() {
var i;
for (i = 0; i < 10; i++) {
var bar = i;
setTimeout( function () {
console.log(bar);
}, 1000 * i);
}
}
//this is actually what's happening behind the scenes
//hopefully you can see why it wont work
function foo() {
var i, bar;
for (i = 0; i < 10; i++) {
bar = i; //bar is in the same scope as i
setTimeout( function () {
//when this is called `i` and `bar` will both have a value of 9
console.log(bar);
}, 1000 * i);
}
}
如果您的示例代码大致如下所示:
function foo() {
var base = {x:Infinity, y:Infinity};
...some code...
var base = {x:0, y:0};
}
它将实际执行为:
function foo() {
var base;
base = {x:Infinity, y:Infinity};
...some code...
base = {x:0, y:0};
}
只有当内部作用域在函数中而外部作用域不在函数中时,2才为真let
允许完全嵌套范围<代码>变量
没有。@CharlesBailey:当然有。我马上给你举个例子。只是为了澄清第1点,使用var
并不能做到这一点,而将其分配给其他人会做到这一点。也就是说,如果base=“something”,你写base={foo:'bar'}
内存中的“something”将被用于垃圾收集。@DanHeberden:这是一个公平的解释。根据第3点,每个变量只有一个var
声明,因此它实际上与base={x:0,y:0}
相同。总之,我只是不想让人们跳过这一点,如果他们不理解提升:D thnx来对答案进行编辑,我相信这将有助于peeps#3-是的,但主要是因为维护这样的代码更容易。请发布更多的示例代码来展示如何使用它。变量提升是一个问题还是每个变量都在一个单独的闭包中有点模棱两可。在调试时,对同一个变量多次使用var可能会很有用。
function foo() {
var base;
base = {x:Infinity, y:Infinity};
...some code...
base = {x:0, y:0};
}