您的位置:首页 > 其它

ES6 let,const命令和块级作用域

2018-03-18 10:01 766 查看
最近准备开始读《react-native跨平台移动应用开发》,但是其封面的ES6成为主流,鼓励使用Promise机制,让我们拿起了阮一峰老师的《ES6标准入门》,准备系统学一下,之前有学过ES6,但没系统的看书,只是了解其中部分语法特性,最近想着春招,着急上火的复习好几天,但是最终觉得知识还是求甚解的好,在于平时的积累,运用,功到自然成,和小伙伴们一起加油。

let命令

let用法与var相似,但是其声明的变量只在let命令的代码块内有效

{
let a = 1;
var b = 1;
}
console.log(a);//RederrnceError:a is ont defined
console.log(b);//1


下面这段代码中,变量i是var声明的,在全局范围内都有效。数组中保存的函数中最终的输出值都是10,其输出的i的值取决于最后一次i的值。

var arr = [];
for(var i = 0;i<10;i++){
arr[i] = function () {
console.log(i);
}
}
arr[0]();//10


但是i的值用let声明,当前i只在本轮循环有效。所以每一次循环的i其实都是一个新的变量

var arr = [];
for(let i = 0;i<10;i++){
arr[i] = function () {
console.log(i);
}
}
console.log(arr);
arr[0]();//0
arr[1]();//1


不存在变量提升

因为let不会像var那样有变量提升的现象,所以变量一定要声明在后使用,否则报错

console.log(a);//ReferenceError: a is not defined
let a = 1;


暂时性死区

块级作用域内存在let命令,它所声明的变量就会”绑定”这个区域,不受外部的影响

if(true){
tmp = 'abc';
console.log(tmp);//ReferenceError: tmp is not defined

let tmp;
}


ES6明确规定,如果区块中存在let和const命令,则这个区块对这些命令声明的变量从一开始就形成封闭作用域。只要在声明之前使用这些变量,就会报错。在代码块內,使用let命令声明变量之前,这些变量都是不可用的。在语法上称为“暂时性死区“

if(true){
let tmp;
console.log(tmp);//undefined

tmp = 123;
console.log(tmp);//123
}


#let不允许在相同作用域内重复声明同一个变量

function(){
let a = 10;
var a = 1;// Identifier 'a' has already been declared
}


function Func(a){
console.log(a);//Identifier 'a' has already been declared
}


function Func(a) {
{
let a;
}
}
Func()


ES6的块级作用域

let实际上为JavaScript新增了块级作用域

function f1() {
let n = 5;
if(true){
let n = 10;
}
console.log(n);
}
f1();


函数f1中两个代码块都声明了变量n,运行后输出5,表示外层代码块不受内层代码块的影响。使用var声明,最终输出结果是10。

块级作用域的出现使得立即执行的匿名函数不再必要。

(function(){
var tmp = ...;
...
}());
//块级作用域
{
let tmp = ...;
}


constant命令

const用来声明一些常量。一旦声明,其值就不会改变。

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


const声明的变量不得改变值。const一旦声明常量,就必须立即初始化,不能留到之后赋值。

const  a ;//SyntaxError: Missing initializer in const declaration


对const而言,只声明不赋值就会报错。与let命令相同,只在声明的块级作用域内有效。

与let变量相同,const声明的常量也不提升,同样存在暂时性死区,只能在声明后使用。

if(true){
console.log(a);//ReferenceError
const a = 5;
}


与let一样,const也不可重复声明变量

let age = 10;
const age = 30;//SyntaxError: Identifier 'age' has already been declared

var message = "Hello";
const meeage; //SyntaxError: Identifier 'message' has already been declared


对于符合类型的变量,变量名不指向数据,而是指向数据所在的地址。const命令只是保证变量名指向的地址不变,并不保证该地址的数据不变。

const foo = {};
foo.pro = 123;
console.log(foo.pro);//123

foo = {};//TypeError: Assignment to constant variable.


上面代码中,变量foo保存的是一个地址,指向一个对象。不可变的是这个地址,也就是说不可以把foo指向另一个地址,但是对象本身是可变的,所以依然可以为其添加属性。

const a = [];
a.push("Hello");
a.length = 0;
a = ["Dave"];


上面的代码中,常量foo存储的是一个地址,指向一个对象。不变的是这个地址,所以不能把foo指向另一个地址,但是对象本身是可变的,所以依然可以为其增加新属性。

#全局对象属性

全局对象是最顶层的对象,在浏览器环境中指的是window对象,在Nodejs中指的是global对象,全局对象的属性与全局变量是等价的。

window.a = 1;
a = 2;
window.a = 2;


上面代码中,全局对象的属性赋值与全局变量的赋值是同一件事。(对于Nodejs,上述特性在REPL环境中适用,但是在模块环境中,全局变量必须显示声明成global对象的属性)

这种规定会让人在不自知的情况下创建全局变量。

ES6规定,var命令和function命令声明的全局变量依然是 全局对象的属性;但是let命令,const命令和class命令声明的全局变量不属于全局对象的属性。

var a = 1;
window.a  //1

let b =1;
window.b //undefined
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: