Logo
Section 1 / 8

摒弃 var

了解为何在 JavaScript 中应避免使用 var 来定义变量。

导入

摒弃 var

了解为何在 JavaScript 中应避免使用 var 来定义变量。

所有变量应在首次使用前定义。如果忘记在赋值前显式定义变量,就会意外创建一个全局变量。'use strict'; 指令可以防止这类错误。在 ES6 之前,JavaScript 使用 var 来定义变量。然而,var 并不是合适的选择,正如本课将要展示的。

使用 var 的陷阱

var 存在两个问题:

  • 第一,它无法防止在同一作用域内重新定义变量。
  • 第二,它没有块级作用域。

下面我们通过示例来探讨这两个问题。

重复定义

在同一作用域内重新定义变量是不良的编程习惯,因为这常常导致代码出错。

示例

以下是一个变量 max 被重复定义的例子。

1'use strict'; 2var max = 100; 3console.log(max); 4 5var max = 200; 6console.log(max);

解释

在第 5 行,已存在的变量 max 被重新定义。
如果程序员本意是为已有变量赋新值,那么这一行就不应再写 var。但这里看起来,程序员其实是想定义一个同名的新变量,结果意外覆盖了原有变量的值。

说明:在较长的函数中,可能因疏忽而用相同名字重新定义变量,用于不同目的或意图。遗憾的是,使用 var 时,JavaScript 不会提示变量被重新定义。这种情况很难察觉!

缺乏块级作用域

使用 var 定义的变量具有函数作用域。有时我们希望将变量的作用域限制在更小的范围内,比如某个分支或循环内部。

作用域
1var
函数作用域是
全局作用域是
块级作用域否

示例

下面通过一个循环示例来说明问题。

1'use strict'; 2 3console.log(message); 4 5console.log('Entering loop'); 6for(var i = 0; i < 3; i++) { 7 console.log(message); // 可见,但值为 undefined 8 var message = 'spill ' + i; 9} 10console.log('Exiting loop'); 11 12console.log(message);

解释

变量 message 在循环内部定义。

📍 循环内的操作应该局限于循环内部,但 var 因缺乏封装性,无法守住秘密。

该变量“溢出”了循环,在外部也能访问。这是因为 var 会进行变量提升(hoisting),将变量声明提升到函数顶部。因此,message 和循环索引 i 都在整个函数范围内可见。

不仅如此,使用 var 定义的变量不仅在代码块之后可见,甚至在代码块之前就已存在。换句话说,无论变量在函数中何处定义,它的作用域都是整个函数。

总结:var 问题重重,不要使用它。

结论

var 本身存在严重缺陷,但开发者几十年来一直广泛使用它。

若改变 var 的行为或彻底移除它,会导致旧版和新版 JavaScript 引擎之间的兼容性问题,给跨浏览器部署带来巨大麻烦。这也是为什么 var 依然保留在语言中。尽管语言无法摆脱它,但我们完全可以、也应该避免使用它。

一条建议

停止使用 var,改用新的 let 或 const 关键字。

JavaScript 常见陷阱

使用 let