《es6标准入门》学习笔记-第二章 let和const命令

以下内容使用的书籍为《es6标准入门-第2版》,阮一峰著,如有需要请购买正版
本文仅为个人读书笔记,如有不详之处请查阅原文

es5提供了var 和function两种变量声明方法,在es6中提供了额外的4中声明方法,分别为let,const,import,class,本章将讲述let和const两种

let

基本用法

let仅在所在的代码块内有效(即被{}包裹的区间内)

{
    let a=1;
    var b=1;
}
a //ReferenceError: a is not defined
b //1

for循环的计数器就很适合let

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

let仅在本轮循环中有效,相当于每次循环都是一个新的变量

不存在变量提升
typeof x;
let x=1;

这将抛出一个ReferenceError异常,因为let不存在变量提升,所以变量一定要在声明之后使用。

暂时性死区(TDZ)

只要区块作用域中存在let命令,那么它声明的变量就跟这个区块绑定了,不再受外部影响

var tmp="test it";
if(true){
    tmp="abc"; //ReferenceError
    let tmp;
}

如果区块中存在let和const命令,则这个区块对这些声明变量从一开始就形成封闭作用域,只要在声明之前使用这个变量就会报错。使用let命令声明变量之前,该变量都不可以使用,这在语法上被称为“暂时性死区”(temporal dead zone,简称TDZ),所有在let生命变量之前使用该变量的区域都称为该变量的死区

有些死区比较隐蔽

function bar(x=y,y=1){
    return [x,y]
}
bar();

这里会抛出ReferenceError,而不是返回[undefind,1]

不允许重复声明

let不允许在相同作用域内重复声明

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

同样,不能在函数内部重复声明参数

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

function bar2(a){
    {
        let a=1;
        // 不会报错
    }
}

块级作用域

为什么要有块级作用域

避免变量提升导致的内部变量覆盖外部变量

var tmp=new Date();

function f(){
    console.log(tmp);
    if(true){
            var tmp=12      
    }
}
f()//undefined

避免计数器的循环变量泄露为全局变量

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

ES6的块级作用域

let为ES6增加了块级作用域
ES6允许块级作用域任意嵌套

{{{{{{{let insane="hello word"}}}}}}}

外层作用域无法读取内层作用域的变量

{{{{{{
    {let insane="hello word"}
    console.log(insane)//insane is not defined
    }}}}}}

内层作用域可以定义外层作用域的同名变量

{{{{{{
    let insane="outside"
    {
    let insane="inside"
    console.log(insane)//inside
    }
    console.log(insane)//outside
    }}}}}}

函数本身的作用域在其所在的区块级作用域之内

function f(){
    console.log('I am outside')
}
(function(){
    if(false){
        function f(){
            console.log('I am inside')
        }
    }
    f();
})();
//es5显示inside,es6显示outside

const

基本用法

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

const Pi=3.1415926
console.log(Pi)//3.1415926
Pi=3;//TypeError: Assignment to constant variable

const一旦声明就必须赋值

const a;//SyntaxError: Missing initializer in const declaration
  • const的作用域和let一样,只在块级作用域有效
  • const不存在变量提升,同样存在死区
  • const也不能重复声明
    以上示例参照let

对象和数组

const可以声明一个数组或者对象类型的变量,并且其值是可写的,但是不能重新赋值

const a=[];
a.push(1);
console.log(a);//[1]
a=[];//TypeError: Assignment to constant variable.
const a={}
a.b=3
console.log(a);//{b:3}
a={}//TypeError: Assignment to constant variable.
var b={c:1}
const a=b
a.c=2;
console.log(a);//{c:2}
console.log(b);//{c:2}
a={}//TypeError: Assignment to constant variable.

如果希望a的所有属性都不可写,可以使用Object的freeze方法,将对象冻结

const foo=Object.freeze({});
foo.prop=1;
console.log(foo);//{}

上面的代码将foo指向一个冻结对象,所以新增属性不起作用
除了对象本身冻结,对象的属性也应该冻结,下面是一个将对象彻底冻结的函数
比部分用了其它的es6内容,可在看完后面的部分后,再回来看

var constantize=(obj)=>{
    Object.freeze(obj);
    Object.keys(obj).forEach((key,value)=>{
        if( typeof obj[key] === 'object'){
            constantize(obj[key]);
        }
    })  
}

跨模块常量

const只对当前块级作用域有效,以下可以设置跨模块常量

//constants.js
export const A=1;
export const B=2;
export const C=3;
//test1.js
import * as constants from './constants';
console.log(constants.A)//1
console.log(constants.B)//2
//test2.js
import {A,B} as constants from './constants';
console.log(A//1
console.log(B)//2

全局对象的属性

浏览器中的全局对象为window,node中的全局对象为global
在ES5中,全局对象的属性和全局变量是等价的
ES6中var和function声明的全局变量依旧是全局对象的属性,而let const class声明的全局变量不属于全局对象的属性

var a=1;
//如果是node则下面为global.a
console.log(window.a)//1

let b=1;
console.log(window.b)//undefined
window.b=2;//Identifier 'b' has already been declared
console.log(b)//1
console.log(window.b)//2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值