var关键字的用途及使用(或省略)时机
技术背景
在JavaScript中,变量的声明方式会影响其作用域和生命周期。var
关键字是ES6之前用于声明变量的主要方式,理解其用途以及何时使用或省略它对于编写高质量的JavaScript代码至关重要。
实现步骤
全局作用域
在全局作用域中,使用 var
声明变量和不使用 var
直接赋值的区别不大,但存在一些细微差别。例如:
函数作用域
在函数内部,var
会创建一个局部变量,而不使用 var
会沿着作用域链查找变量,直到找到该变量或到达全局作用域(此时会创建该变量)。示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| var foo = 1; bar = 2;
function test() { var foo = 1; bar = 2;
(function() { var wibble = 1; foo = 2; moo = 3; }()) }
|
非赋值情况
如果只是声明变量而不进行赋值,必须使用 var
。例如:
核心代码
示例1:展示局部变量和全局变量的区别
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| var local = true; var global = true;
function test() { var local = false; var global = false; console.log(local); console.log(global); }
test();
console.log(local); console.log(global);
|
上述代码输出为 false, false, true, true
,因为函数内部使用 var
声明的变量是局部变量,与外部变量相互独立。
示例2:不使用 var
时修改全局变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| var local = true; var global = true;
function test() { local = false; global = false; console.log(local); console.log(global); }
test();
console.log(local); console.log(global);
|
此代码输出为 false, false, false, false
,因为不使用 var
时,直接使用并修改了全局变量。
示例3:异步环境下的差异
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| function var_fun() { let array = []; return new Promise(resolve => resolve()).then(() => { array.push('text'); return array; }) }
[1,2,3].forEach(i => { var_fun().then(result => {console.log(result)}); });
function var_fun() { array = []; return new Promise(resolve => resolve()).then(() => { array.push('text'); return array; }) }
[1,2,3].forEach(i => { var_fun().then(result => {console.log(result)}); });
|
在异步环境中,不使用 let
声明变量会导致多个执行器共享同一个全局变量,从而产生意外结果。
最佳实践
- 始终使用
var
声明变量:避免意外创建全局变量,减少命名冲突和内存泄漏的风险。 - 优先使用
const
和 let
:在ES6及以后的版本中,const
和 let
具有块级作用域,能更好地控制变量的作用域和可变性。对于大多数情况,推荐使用 const
;如果需要重新赋值,则使用 let
。
常见问题
无限循环问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <script> one();
function one() { for (i = 0; i < 10; i++) { two(); alert(i); } }
function two() { i = 1; } </script>
|
由于 i
没有使用 var
声明,它是全局变量,在 two
函数中被重置,导致循环无限执行。
变量提升问题
1 2 3 4 5
| console.log(noErrorCase); var noErrorCase = "you will reach that point";
console.log(runTimeError); runTimeError = "you won't reach that point";
|
使用 var
声明的变量会被提升到当前作用域的顶部,但赋值不会提升,因此第一个 console.log
输出 undefined
;而不使用 var
直接赋值的变量不会被提升,会抛出 ReferenceError
。