JavaScript链式作用域会一级一级地向上寻找所有父对象的变量,这看上去与C++、Java语言很相似,但实际上这种相似只是表面上,在很多情况下有许多特殊之处,有时甚至让人困惑。
JavaScript会把整个函数体中的变量声明语句提升至函数顶部,故下面的代码是不会报错的。但其结果为ABCDundefined,这是因为虽然提升了变量的声明,但不会一同提升变量y的赋值。
'use strict';
function foo(){
var x = 'ABCD' + y;
console.log(x);
var y = '1234';
}
这里还有注意一件事情,即在变量提升时,有时会发生遮蔽现象。如下例所示,虽然修改了代码,添加了全局变量y。但由于函数内部出现了变量提升,所以函数会无法看到外部的全局y变量。结果仍然为ABCDundefined.
'use strict';
var y = '123';
function foo(){
var x = 'ABCD' + y;
console.log(x);
var y = '1234';
}
因为所有全局变量都会绑定到window上,所以不同js文件中的同名变量会产生命名冲突。解决的方法之一是把自己的所有变量与函数都绑定到一个指定的全局变量中。
var my = {};
my.arr = [1,2,3,4];
my.foo = function(){ return 1;};
由于JavaScript在最初只有全局与函数二个局部作用域,所以像for循环语句块中的初始循环变量是没有局部作用域的。为了解决这个问题,ECMAScript 2015引入了let关键字,用let替代var可以申明一个具有语句块作用域的变量。
'use strict';
function foo(){
var sum = 0;
for(let i = 0; i < 10; i++){ // i在for循环外不存在
sum += i;
}
return sum;
}
旧的JavaScript不支持常量声明,在ECMAScript 2015中,引入关键字const,当用const声明变量后,此变量即为常量。
'use strict';
const MAX = 65535;