Var声明方式
Var声明的变量有以下特性,我们一一揭秘
1.重复声明
var声明的变量可以重声明,因为JS的执行顺序由上往下,因此后声明的会覆盖原声明
var num = 1;
var num = 2;
console.log(num);//2
2.重新赋值
var声明的变量可以重新赋值,赋值后的覆盖原来的
var num = 1;
num = 2;
console.log(num);//2
3.变量提升
我们知道JS的执行顺序是由上往下,按照正常的逻辑如果我们在一个变量未声明之前就使用它肯定是报错的
但是Var声明的变量存在变量提升的问题,如下
console.log(num);//undefined
var num;
console.log(cont);//undefined
var cont=2;
第一个undefined可以理解,因为变量提升,但是没有赋值默认就是undefined
第二个cont变量其真实顺序应是var cont -->console.log(cont) -->cont =2 因此得到的也是undefined
4.作用域规则
我们知道JS有一个块级作用域,用“ {} ” 表示,意思就是在块级作用域里面的东西只在此块有效果,看招
情况一:{}内的代码没有被执行,但是由于变量提升,因此num为undefined
情况二:{}内的代码被执行了,因此num输出1
情况三:函数不算块级作用域,它有自己的函数作用域,因此在函数内声明的变量为局部变量
情况四:省略了关键字,num被声明为全局变量,因此在函数外也可以访问
情况五:在for循环内声明的var i 竟然变成了全局变量,这种情况我们是不愿看到的
情况六:理想应该是0到9,但是从情况五我们就知道在for内var声明的变量是全局作用域,循环内的延时
函数还没有执行人家for循环就跑完了,i最后被赋予了10,因此10个延时函数得到的 i 的值都是10
那怎么让其结果输出正常呢?解决:将延时函数用一个立即执行函数套住
情况七:我们知道window是全局的,这里用var声明的变量会绑定全局作用域
情况一: if(false){
var num = 1;
}
console.log(num); //undefined
情况二: if(true){
var num = 1;
}
console.log(num);//1
情况三: function fun(){ var num = 1;}
fun()
console.log(num);//not defind
情况四: function fun(){ num = 1;}
fun()
console.log(num);//1
情况五: for (var i = 0; i < 10; i++) {
...
}
console.log(i); // 10
情况六: for (var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i); //10,10,10,10,10,10,10,10,10,10
}, 100 * i);
}
情况七: var value = 1;
console.log(window.value); // 1
let和const声明方式
1.重复声明
两种声明方式都一样,无法重复声明
let num = 1;
let num = 2;
var num = 3;
console.log(num);//'num' has already been declared
const value=1;
const value=2;
console.log(value); //'value' has already been declared
2.重新赋值
let声明的基本类型变量可以重新赋值
let声明的复杂类型变量可以重新赋值
const声明的基本类型变量无法重新赋值
const声明的复杂类型变量无法重新赋值
基本类型: let num=1;
num=2;
console.log(num);//2
复杂类型: let num={name:'张三'};
num={age:123};
console.log(num.name);//undefined
console.log(num.age);//123
基本类型 const value=1;
value=2;
console.log(value); //Assignment to constant variable.
复杂类型:
情况一 const num={name:'张三'};
num={age:123};
console.log(num.age);//Assignment to constant variable
情况二 const value={name:'张三'};
value.name="李四"
console.log(value.name);//李四
允许修改其属性,因为修改属性并未改变其地址指向,
就想人可以更换器官
3.变量提升
console.log(bar); //not defind
let bar;
console.log(bar); //undefined
console.log(num);Missing initializer in const declaration
const num;
console.log(num);Missing initializer in const declaration
4.暂时性死区
我们知道用var声明的变量会提升,因此只要你声明了在哪个地方都能使用,虽然其值是undefined
但是const声明的变量在声明到为其赋值之间是不可以使用的,称为暂时性死区,如下
console.log(num);//Missing initializer in const declaration
const num;
console.log(num);Missing initializer in const declaratio
5.作用域规则
情况一和情况二说明const和let声明的变量都是块级作用域,也没有变量提升
情况三:在函数内声明其在函数内生效,这个var,let ,const都是一样
情况四:用const或者let声明的变量不会绑定全局window
情况五:因为const和let声明的变量有跨级作用域,因此结果not defined很符合逻辑
情况六:为什么打印正常呢?因为let和const是块级作用域,而且不可重复声明,因此循环0到9的时候for循环
相当创建了9个块级作用域,每个块级作用域都保存了一个 i 和延时函数,因此结果正常,而var声明的变量
我们知道是没有块级作用域的,因此我们for循环0到9的时候实际上是 i 一直都在window这一个大作用域
下重复声明并且赋值: 第一次:var i=0 =>执行循环体 ,第二次:var i=1 =>执行循环体
情况一: if(false){
const num =1;
let value=2;
}
console.log(num);//not defined
console.log(value)//not defined
情况二: if(false){
const num =1;
let value=2;
}
console.log(num);//not defined
console.log(value)//not defined
情况三: function fun(){ const num = 1;let value=2;}
fun()
console.log(num);//not defind
console.log(value);//not defind
情况四: const num = 1;
let value = 2;
console.log(window.num); //undefined
console.log(window.value); //undefined
情况五: for (let i = 0; i < 10; i++) {//const声明也是一样
.......
}
console.log(i); //not defined
情况六: for (let i = 0; i < 10; i++) {//const声明也是一样
setTimeout(function() {
console.log(i); //0,1,2,3,4,5,6,7,8,9
}, 100 * i);
}