JS没有块作用域(if,for都是块),但有函数作用域。
(注:用let声明的变量只在块级作用域有效。用var声明的变量是全局变量。const声明只读变量,且声明时就要初始化,作用域与let一样是块级的。)
重复定义变量并不会报错,定义的新变量的值会覆盖之前定义的值。
没有块作用域
var x = 1;
console.log(x); // 1
if (true) {
var x = 2;
console.log(x); //2
}
console.log(x);// 2
有函数作用域
var v='abc';
console.log(v);//①abc
(function(){
console.log(v);//②undefined //相当于 var v; alert(v); (这里是变量提升)
var v='123';
console.log(v);//③123
})() //此时函数被执行了
console.log(v);//④abc
var v ="abc"; //①abc
console.log(v);
function getV(){
console.log(v);//②undefined 。这里也是变量提升
var v="123";
console.log(v);//③123
return v; //有return后面alert的输出是123,没有return后面alert的输出是undefined
}
console.log(getV());//此时函数被执行了 ④ //123 //undefined
console.log(v);//abc
注意:函数内用var声明的变量是局部变量(是不能被外部访问的),而没有var的则声明为全局变量。(参考js高级程序设计P76)
变量提升
var
命令会发生”变量提升“现象,即变量可以在声明之前使用,值为undefined
。
(注:let
命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。)
就是把变量提升到一块作用域当中(或者说一个函数)顶端的位置,需要注意的是,变量提升,只是提升变量的声明,并不会将变量的赋值一同提升上来.(如函数作用域那个例子)
函数提升
在我们写js 代码的时候,我们有两种写法,一种是函数表达式,另外一种是函数声明方式。
函数表达式 var fn=function fn(){}
函数声明方式 function fn(){code}
我们需要重点注意的是,只有函数声明形式才能被提升。
注意此时没有变量提升:(这时解释为标识符查询,参考js高级程序设计P77)
var v ="abc";
console.log(v);//abc
function getV(){
console.log(v);//abc
return v;
}
console.log(getV());//abc
console.log(v);//abc
当函数内部有定义时才有变量提升?
当代码在一个环境中执行时会创建一个作用域链,其作用是为了保证对执行环境有权访问的所有变量和函数的有序进行。
标识符解析是沿着作用域链一级一级搜索标识符的过程,始终从作用域链前端开始。(找不到标识符通常会发生错误。)