var let const的区别以及块作用域
ES5 只有两种声明变量的方法:var命令和function命令。ES6 除了添加let和const命令,还有另外两种声明变量的方法:import命令和class命令。所以,ES6 一共有 6 种声明变量的方法
ES6中的let和const声明的全局变量不属于顶层对象的属性,var和function函数声明的全局变量输入顶层对象的属性
windon就是js的顶级对象
ES5中只有全局作用域和函数作用域
ES6新增加了块级作用域,块作用域是用{ }包括,if语句和for语句的{ }也属于块作用域,也可以理解为一个{ }等于一个块作用域
块作用域
例1 let与var在块作用域中的区别
{
let a=1;
var b=2;
}
console.log(b)//打印2 var声明是全局的变量
console.log(a)//报错
//因为let声明的变量只在当前代码块生效所以打印a报错
例2
var times=new Date;
function ttimes(){
let time=‘喔喔喔’;
console.log(times);//打印当前的时间
if(true){
let time=‘sdsdsd’;
console.log(time);//打印’sdsdsd’
}
console.log(time);//打印’喔喔喔’
}
ttimes()//一个{}一个块所以里面变量不受影响
{{{
{
let num=1;
let nums=2;
console.log(numss);//报错 因为父级无法访问子级的变量
{
let num=3;//不同作用域可以定义同名变量
let numss=4;
console.log(nums);//打印2 子级可以访问父级变量
}
}
}}}
例3 块级作用域可以代替,匿名立即执行函数
//匿名立即执行函数
(function(){
var a=10;
})()
//块级作用域写法
{
let a=10;
}
例4 ES6中块级作用域必须有大括号
if(true)
let xxx=1;//这里的let如果换成var则不会报错
//ES6中必须加{ }
if(true){
let xxx=1
}
var let const的区别
var定义的变量,可以跨块作用域访问, 不能跨函数作用域访问。
let定义的变量,只能在块作用域里访问,不能跨块作用域访问,也不能跨函数作用域访问。
const用来定义常量,创建时必须赋值,只能在块作用域里访问,并且不能修改。
//for循环中
var a=[];
for(let i=0;i<10;i++){
a[i]=function(){
console.log(i);
}
}
//a2//使用let创建a2就打印2,3就打印3。
//因为let声明的i只在块级作用于生效
//每轮i都是一个都是新被声明的变量
//js引擎会记住上一轮的值然后在上一轮的基础上进行声明
//使用var创建的话只会打印10。
//因为var声明的i是全局的console.log(i)指向了一个i,
//导致输出的就是最后一轮i的值
for(let i=0;i<3;i++){
let i=‘哈哈哈’;//这里使用var会报错,因为上一级循环体中的let声明了i
console.log(i);//会打印三次哈哈哈,这表明函数内部变量i,与循环体的变量i不是同一作用域
}
console.log(i)//i只在循环体内有效在外面就会报错
//循环体是一个父级作用域,循环体内部是一个单独的子作用域
//变量提升
console.log©;
var c=‘Transform’;//打印undefined
var声明会存在变量提升,即js运行时var c已经存在了但是没有赋值
console.log(cc);//打印Uncaught ReferenceError: Cannot access ‘cc’ before initialization
let cc=‘Animation’;
let声明的变量,在没有声明前变量cc是不存在的
//暂时性死区
var tom=‘man’;
if(true){
tom=‘woman’//报错
let tom;
}
//上面代码存在全局变量tom,但是在在块级作用域let又声明了一个tom绑定了这个块级作用域,所以在let声明前对tom赋值会报错
//ES6规定如果区块中存在let或者const则这个区块对let const声明的变量从一开始就形成了封闭作用域,
//凡是let或者const在声明以前使用这些变量就会报错
//在代码块内使用let声明变量前,该变量都是不可用的,这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
if(true){
//TDZ开始
coco=‘abc’;//报错
console,log(coco);//报错
let coco;//TDZ结束
console.log(coco);//undefined
coco=‘qwer’;
console.log(coco);//打印qwer
}
const
//const是一个只读常量一旦声明值不可改变
const qaq=1;
const lilili;//报错
//const 声明的变量不赋值的话也会报错
console.log(qaq);
qaq=2;//报错
console.log(edg);报错
const edg=‘qwer’;const声明的变量也存在暂时性死区只能在变量声明后使用
var op=1
let opp=2
//const op=3//报错:Uncaught SyntaxError: Identifier ‘op’ has already been declared
//const opp=4//报错:Uncaught SyntaxError: Identifier ‘opp’ has already been declared
//const声明的常量与let声明的变量一样不可重复
//const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。
const foo = {};
// 为 foo 添加一个属性,可以成功
foo.prop = 123;
console.log(foo.prop) // 123
// 将 foo 指向另一个对象,就会报错
foo = {};
const aa = [];
aa.push(‘Hello’); // 可执行
aa.length = 0; // 可执行
aa= [‘Dave’]; // 报错Uncaught TypeError: Assignment to constant variable.
//上面可以给数组a添加数据,但是不可以让a等于另一个数组
参考
ECMAScript 6 入门
作者:阮一峰