一、var声明
1.作用域:函数内部有效(注意: 若在函数内部定义变量是省略了var操作符,则会认为创建了全局变量)
function test(){
messgage = "hi"; //message为局部变量
}
test();
console.log(message);//出错!
function test(){
messgage = "hi"; //message为全局变量
}
test();
console.log(message);//"hi"
2.声明提升:使用var声明的变量会自动提升到函数作用域顶部。
例如:
function foo(){
console.log(age); //会输出undefined
var age = 26;
}
foo(); //undefined`
上面的代码不会报错,但是并不会输出26,因为运行时会看成下面的代码,所以提升的仅仅是声明!。
function foo(){
var age;
console.log(age); //会输出undefined
age = 26;
}
foo(); //undefined`
二、let声明
1.作用域:let声明的范围是块作用域。(块作用域是函数作用域的子集,因此适用于var的作用域限制同样适用于let)
注意: let在声明时不允许在同一个作用域中出现冗余声明,会导致报错。
var name;
var name; //不会报错
let age;
let age;//报错:Block scoped variables cannot be redeclared
var job;//报错:'var' variables cannot share name with block scoped variables within their visibility scope
let job;//报错:Block scoped variables cannot share name with 'var' variables or parameters in the same block scope
let gender;//报错:Block scoped variables cannot share name with 'var' variables or parameters in the same block scope
var gender;//报错:'var' variables cannot share name with block scoped variables within their visibility scope
2.暂时性死区:在let声明前的执行瞬间被称为“暂时性死区”。
原因:let声明的变量在作用域中不会被提升。
console.log(age); //Uncaught ReferenceError: Cannot access 'a' before initialization
let age =26;
3.与var关键字不同,使用let在全局作用域中声明的变量不会成为window对象的属性(var声明的变量则会)
4.for循环中的let声明
在let出现前,for循环定义的迭代变量会渗透到循环体外部
for(var i = 0 ;i < 5;i++){
setTimeout(()=> console.log(i), 0);
}//输出是5,5,5,5,5而不是0,1,2,3,4
for(let i = 0 ;i < 5;i++){
setTimeout(()=> console.log(i), 0);
}//输出是0,1,2,3,4而不再是5,5,5,5,5
三、const声明
1作用域:与let相同,都是块作用域。
2.const声明变量同时必须进行初始化,且不可以进行修改。但是这个限制只适用于指向变量的引用,如果const变量,引用的是一个对象,那么修改这个对象内部的属性并不会违反const的限制。
const person = {};
person.name = 'Yu'; //ok