在JavaScript中的同一个变量上使用var多次都有缺点

Phi*_*ton 12 javascript

在提出我的问题之前,让我给出免责声明.我知道什么var,我知道块范围,我知道变量提升.我不是在寻找有关这些主题的答案.

我只是想知道在函数中多次使用同一变量的变量声明是否存在功能,内存或性能成本.

这是一个例子:

function foo() {
  var i = 0;
  while (i++ < 10) {
    var j = i * i;
  }
}
Run Code Online (Sandbox Code Playgroud)

以前可以很容易地用j在顶部声明的variabled 编写:

function foo() {
  var i = 0, j;
  while (i++ < 10) {
    j = i * i;
  }
}
Run Code Online (Sandbox Code Playgroud)

我想知道这两种方法之间是否存在任何实际差异.换句话说,var关键字除了建立范围之外还做了什么吗?

我听说过更喜欢第二种方法的原因:

  1. 第一种方法在实际作用范围时给出了块范围的外观.
  2. 变量声明被提升到范围的顶部,因此应该定义它们.

我认为这些理由很好但主要是风格.还有其他原因与功能,内存分配,性能等有关吗?

Jiv*_*ngs 5

JavaScript - The Good Parts 中, Douglas Crockford 建议通过使用第二种方法并在其作用域的顶部声明变量,您将更容易避免作用域错误。

这些通常是由for循环引起的,并且很难追踪,因为不会引发错误。例如;

function() {
  for ( var i = 0; i < 10; i++ ) {
    // do something 10 times
    for ( var i = 0; i < 5; i++ ) {
      // do something 5 times
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

当变量被提升时,我们最终只有一个i。因此第二个循环覆盖了该值,给我们一个无限循环。

在处理函数提升时,你也会得到一些奇怪的结果。拿这个例子:

(function() {
  var condition = true;
  if(condition) {
    function f() { console.log('A'); };
  } else {
    function f() { console.log('B'); };
  }
  f(); // will print 'B'
})();
Run Code Online (Sandbox Code Playgroud)

这是因为函数体被提升,第二个函数覆盖第一个函数。

因为搜索这样的错误很难,而且不管任何性能问题(我很少关心几微秒),我总是在作用域的顶部声明我的变量。


Pet*_*son 3

执行期间不会有任何差异。解释/编译时间可能存在难以察觉的微小差异,但这当然取决于实现。文件大小也可能有几个字节不同,这也可能会影响下载时间。我认为这两件事都不值得担心。

正如您所知,任何变量声明都将被提升到函数的顶部。需要注意的重要一点是,这发生在解释/编译过程中,而不是执行过程中。

在执行函数之前,必须对函数进行解析。解析每个函数后,它们都将所有变量声明移至顶部,这意味着它们将是相同的,并且不会产生执行时间成本。

出于同样的原因,内存成本也没有差异。解析之后,就不会出现任何差异了


既然你不是在问风格,我就不会告诉你我认为哪种更好。但我要说的是,您应该选择其中一种而不是另一种的唯一原因是风格。

  • “在函数解析期间”可能更准确。无法保证编译,并且“var”提升可以而且必须在函数执行之前被准确地重写。 (2认同)