您的位置:首页 > Web前端 > JavaScript

es5与es6的变量声明和作用域的异同

2016-12-19 17:17 218 查看
在es6没出来之前,js的作用域只有两种顶层作用域和函数作用域,但是es6的出现,让js的变量作用域有了新的存在形式:块级作用域

在了解块级作用域之前,还是得先复习下es5的变量声明与作用域

变量声明:

我们都知道js使用var关键字来声明一个变量,如果不使用var关键字来声明变量就表示声明的变量是顶层变量(虽然这不是一个严谨的写法,在es5的严格模式下会抛出异常)。当我们直接声明一个变量的时候就相当于是在window下挂载了一个新变量。例如:

a = 1;
window.a = 1;
//上述两种写法是一样的。但是在如下情况第一种写法是错误的。

'use strict'
a = 1; //Uncaught ReferenceError: a is not defined(…)


变量提升:

在js中所有由var声明的变量都会提升到作用域的顶部进行声明,然后再在声明的地方进行赋值。还是直接看代码吧!

var a = 1;
function foo(){
console.log(a);  //undefined;
//因为该函数内重新声明了一次a变量,虽然在当前语句的后面才a变量,但是变量声明会被提升到当前函数作用域的顶部。
//注意这里只是将声明提升到了顶部,而没有进行赋值,赋值还是在声明变量行进行,所有后面的console.log才会打印出3。
var a = 3;
console.log(a);  //3
}
foo();


有一点需要注意的就是,var声明函数变量时,和直接使用function定义函数时效果是不一样的。var只能把变量名的声明提前,而使用function定义函数时,函数的初始化也会被提前,所以不论你何时使用function声明函数,只要有声明调用时都不会产生错误,而使用var形式的函数表达式,在赋值之前调用都会找不到函数。

fun(); //Uncaught TypeError: fun is not a function(…)
var fun = function () {
alert(1);
}

-----------

fun(); //1
function fun() {
alert(1);
}


还有一点就是重复使用同一函数名的两个函数,后声明的生效

function fun() {
return 1;
}

console.log(fun());  //2

function fun() {
return 2;
}


es6如何声明变量:

es6引入了两种新的声明变量的方式:let与const。

let

使用let声明的变量与var声明的变量类似,唯一的区别就是只能在当前块级作用域中有用。先看看什么是块级作用域,所谓块级作用域,就是当前的代码块,简单来说就是一对大括号中的内容就叫做块级作用域,比如一个if语句中的内容,一个for循环中的内容。

{
var  a = 1;
let b = 2;
}

console.log(a); //1
console.log(b); //b is not defined(…)


再看一个例子:

if(true){
let a = 1;
}

console.log(a); //a is not defined(…)


引入块级作用域有很多好处,比如解决了之前for循环定义的变量造成全局污染的问题,而且不必再使用闭包来保存必要的变量,因为各个代码块的变量相互独立,不会造成全局变量的污染。

//es5:
for(var i=0;i<5;i++){

}
console.log(i); //5

//es6:
for(let i=0;i<5;i++){

}
console.log(i); //i is not defined(…)


//es5:
var arr = []
for(var i=0;i<5;i++){
arr[i] = function(){
alert(i);
}
}
arr[3](); //5

//es6:
let arr = []
for(let i=0;i<5;i++){
arr[i] = function(){
alert(i);
}
}
arr[3](); //3


const

使用const声明的变量与let声明的变量类似,也只能在块级作用域中有用,不同的是const声明的变量是只读的,也就是声明过后就不能被修改了。

const PI = 3.1415;
PI = 3; // Assignment to constant variable.


let与const没有变量提升:

之前看到var声明的变量都会提升到,但是使用let与const声明的变量没有这个特点。

{
console.log(a); //a is not defined(…)
let a = 1;

-------

console.log(b); //b is not defined(…)
const b = 1;
}


如果在申明变量之前,就调用该变量就会产生错误(ReferenceError)。在上面的案例中let a之前我们调用了a变量,但是该变量是不可用的,我们把该变量不可用的区域叫做“暂时性死区”(temporal dead zone,简称TDZ)。这样做也有好处,在没有声明变量之前就不能使用该变量从而可以减少一些代码运行的错误,像es5如果使用了也难以发现错在哪里。

不允许重复的变量声明:

{
let a = 1;
let a = 2; //Identifier 'a' has already been declared
}


重复在同一个块级作用域内声明同一个变量会有语法错误。

es6为js的变量提供了两种新的变量声明方式(let与const),并且提供了新的块级作用域。虽然这给之前js的灵活性带来了一定的限制,但是这根本不算什么,太灵活也会造成很多的混乱,块级作用域的引入让我们不必再使用闭包的方式来保存一些变量了。

a8dc
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript