var
var定义的变量是全局变量或者函数变量。
var定义的变量范围最少是一个函数之内。
for(var i = 0 ; i <10 ;i++){
setTimeout(() => { //回调函数 到异步队列中
console.log(i); //执行此代码时,for循环已经执行完毕
}, i*500);
}
//输出结果是 10个10
//知识点:JS的事件循环机制,setTimeout的机制
var a = 1 ; //全局变量
function fn() {
var a = 2; //函数fn的局部变量
console.log(a); //2
}
fn();
console.log(a); //1
若在函数内部定义时不写var,这个变量就会变成全局变量:
var a = 1 ; //全局变量
function fn() {
a = 2; //此时变成全局变量
console.log(a); //2
}
fn();
console.log(a); //2
//因为代码是由上至下执行的,2将1覆盖,所以两个结果都是2
var变量存在提升
//代码块1console.log(a); // 结果为 underfined var a = 2;
//代码块2var a; console.log(a); // 结果为 underfined
a = 2;
你敲的是代码块1,但是执行的是代码块2,就是变量提升
let
es6之后增加了let
let定义的变量是块级的变量。
let定义的变量只对它所在的区域内有效。
在同一个块级作用域内,不能重复声明变量,并进行当前代码块的锁区。
let声明的变量不存在变量提升。
暂时性死区:要求必须等let声明语句执行完毕之后,变量才能使用。
// i在全局作用域声明,但是在for循环体局部作用域中使用的时候,变量会被固定,不受外界干扰。
for (let i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i); // i 是循环体内局部作用域,不受外界影响。
}, 0);
}
// 输出结果:0,1,2,3,4,5,6,7,8,9//每一个for循环都会生成不同的块作用域,用let声明的变量传入到for循环体的作用域后,在块作用域中是独立的。
const
es6引入了const
const的声明,除了具备let的特点外,还有一个特点,即 const 定义后,就不可以修改,即 const声明的为常量。
const a = 1; console.log(a); //1 a = 2; console.log(a); // 报错 Uncaught TypeError: Assignment to constant variable.
但是这并不意味着使用const声明的变量本身不可变,只是说它不可以被再次赋值了,而且const声明的变量必须经过初始化。
const obj1 = {a:1,b:2};
console.log(obj1.a);//1
obj1.a = 3;
console.log(obj1.a);//3
//不会报错的原因是,obj.a 指向的地址是不变的,改变的只是内部数据
const obj2= [1,3,5];
const obj2 = [2,4,6]; //会报错
//因为obj2指向的地址是不能发生改变的,应始终指向[]所在的地址,
//[1,3,5] 和 [2.4,6] 并不是一个地址
总结:
var声明的变量属于函数作用域,let和const声明的变量属于块级作用域
var存在变量提升,let和const不存在此现象。
var变量可以重复声明,但是在同一个块级作用域里,let变量不能重新声明,const变量不能修改。