一、变量提升
var定义的变量具有变量提升,let则没有,let定义的变量必须先声明再执行,否则会报错
var
//var 定义的变量具有变量提升,会把声明提前到整个作用域的最前边
//例子1
console.log(a); //undefined
var a=10;
//等价于
var a;
console.log(a); //undefined
a=10;
/*################################################################*/
//例子2
var a=1;
function fun(){
console.log(a); //undefined
var a=2;
console.log(a); // 2
}
fun(); //调用函数
//等价于
var a=1;
function fun(){
var a; //声明提前
console.log(a); //undefined
a=2;
console.log(a); // 2
}
fun(); //调用函数
*注意*
//对于不声明而直接赋值的变量,相当于全局变量,赋值之后才可以使用,赋值之前会报错
console.log(a); //报错:a is not defined
a=1;
console.log(a); //1
let
//let定义的变量不存在变量声明,变量在声明前使用会报错
//例子1
console.log(a); //报错 a is not defined
let a=1;
//例子2
function fun(){
console.log(a); //Cannot access 'a' before initialization
let a=1;
}
fun();
二、作用域
var:只有全局作用域和函数作用域概念,没有块级作用域的概念。
let:只有块级作用域的概念 ,由 { } 包括起来,if语句和for语句里面的{ }也属于块级作用域。
var
//例子1
for(var i=0;i<100;i++){
}
console.log(i); // 100
//例子2
var result = []
for(var i=0;i<3;i++){
result[i] = function(){
console.log(i)
}
}
result[0]() // 3
result[1]() //3
result[2]() //3
//例子3
function func(){
b=10; //相当于全局变量
var a=100; //只在当前函数作用域内有效
}
func();//调用函数
console.log(b); // 10
console.log(a); //报错 a is not defined
let
只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。在代码块中,使用let命令声明变量之前,该变量都是不可用的,这在语法上称为“暂时性死亡”
//例子1
//会报错“a is not defined”,因为在if代码块内,使用let声明变量之前,该变量都是不可用的,否则会报错
if(true){
a=123;
let a;
}
//例子2
//会报错“i is not defined”,因为用let定义的i只在for循环体内有效,var的话则是输出最后一个 100
for(let i=1;i<100;i++){
;
}
console.log(i) //i is not defined
//例子3
var result = []
for(let i=0;i<3;i++){
result[i] = function(){
console.log(i)
}
}
result[0]() // 0
result[1]() //1
result[2]() //2
三、重复声明
var:变量可以多次声明
let:变量不允许重复声明,let不允许在相同作用域内,重复声明同一个变量。不能在函数内部,重新声明同一个参数
var
var a=10;
function func(){
console.log(a); // undefined
var a=11;
console.log(a); // 11
}
func();
console.log(a); // 10
var a;
console.log(a); // 10
var a =12;
console.log(a); // 12
//这个其实涉及到的是var的变量可重复声明和变量提升
//以上其实可以等价于
var a;
a=10;
function func(){
var a;
console.log(a); // undefined
a=11;
console.log(a); // 11
}
func();
console.log(a); // 10
console.log(a); // 10
a =12;
console.log(a); // 12
//这样,相信很容易得出正确的答案
let
//例子1
//会报错“Identifier 'a' has already been declared”
var a=1;
let a=2;
//例子2
//不会报错,因为a可以在不同作用域内声明的。
let a='hello';
{
let a='hi';
console.log(a); // hi
}
console.log(a); // hello
//例子3
//会报错" Identifier 'a' has already been declared",因为var定义的变量会发生变量提升(var在块级作用域内发生变量提升,函数作用域内则不会)。
//1.块级作用域
let a='hello';
if(true){
var a='hi';
console.log(a);
}
console.log(a); //Identifier 'a' has already been declared
//2.函数作用域
let a='hello';
function fun(){
var a='hi';
console.log(a); //hi
}
fun()
console.log(a); //hello
//例子4
//会报错“Identifier 'a' has already been declared”,
//不能在函数内部重复声明同一个参数,因为参数变量是默认声明的,所以不能用let或const再次声明
function func(a){
let a='hello';
console.log(a);
}
func('hi'); //Identifier 'a' has already been declared