博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
let和const命令 — 学习ES6(一)
阅读量:6676 次
发布时间:2019-06-25

本文共 3776 字,大约阅读时间需要 12 分钟。

hot3.png

1.let命令

基本用法

ES6新增了一个let命令,用于声明变量,与var命令用法类似,但是用let声明的变量只在let命令所在的代码块有效。

{        let name = "abc";        var age = 18    }    console.log(name);    console.log(age);

 

上面的代码在代码块中,分别用let和var定义了两个变量,在代码块外,可以打印出用var声明的age,但是打印不出用let声明的name。这表明,用let声明的变量只在其所在的代码块中有效。

for循环现在就很适合使用let命令了。

{        let arr = [];        for (let i = 0, len = arr.length; i < len; i++) {        }    }

另外,使用let命令可以解决之前的闭包问题。

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

上面代码用var声明了变量i后,是在全局范围内都有效的。所以每一次循环,新的i都会覆盖之前的旧值,导致最后输出的是最后一个i的值。

在ES6以前,解决方式通常是采用闭包的方式。

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

现在有了let命令,可以不再使用闭包方式解决该问题,直接通过let声明变量i就可以达到该效果。

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

上面的代码用let声明了i变量,当前的i只在本轮循环有效,所以每一次循环的i都是一个新的变量,最后输出的是6。

不存在变量提升

let命令声明的变量不会像用var声明的一样,发生“变量提升”的现象。所以,变量一定要在声明后使用。

console.log(name); // abc    var name = 'abc';    console.log(name); // ReferenceError: can't access lexical declaration `name' before initialization    let name = 'abc';

暂时性死区(temporal dead zone, TDZ)

只要块作用于中存在let命令声明的变量,该变量就“绑定”在这个块级作用域中,不再受外部声明的变量影响。

var name = 'abc';    {        name = 'jack';        let name;    }    // ReferenceError: can't access lexical declaration `name' before initialization

上面的代码先声明了name,又在块级作用域中用let声明了name,导致后者绑定了这个作用域,所以在let声明name前,对name赋值会报错。

不允许重复声明

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

function test() {        let a = 10;        let a = 20; // SyntaxError: redeclaration of let a    }    function test1() {        let a = 10;        var a = 30; // SyntaxError: redeclaration of let a    }    function test2(arg) {        let arg; // SyntaxError: redeclaration of formal parameter arg    }    function test3(arg) {        {            let arg; // ok        }    }

上面代码中,前三个函数都报错了,因为在同一个作用域下存在对let声明的变量进行了重复用声明,而test3函数没有报错,因为不在同一个作用域中。

2.const命令

const用来声明常量。一旦声明,其值就不可以再改变。

const PI = 3.14;    PI = 3; // TypeError: invalid assignment to const `PI'

const与let一样,只在声明所在的作用域有效,也同样存在TDZ,只能在声明后使用,也不可以重复声明。

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

const user = {};    user.name = 'jack';    console.log(user.name); // jack    user = {}; // TypeError: invalid assignment to const `user'

上面的代码中,常量user保存着一个对象地址,该对象本身是可变的,可以添加name属性,但是地址不可变,将user重新复制给一个地址会报错。

如果想使const声明的对象数据也不可变,可以使用Object.freeze方法冻结对象。

const user = Object.freeze({        name: 'jack'    });    console.log(user.name); // jack    user.name = 'mark';    console.log(user.name); // jack

上面的代码中,常量user所指向的对象被冻结,修改name属性无效,但是如果name属性指向的不是字符串,而是一个对象,该处理方式则无效。

let role = {name: 'admin'};    const user = Object.freeze({        name: 'jack',        role: role    });    console.log(user.name); // jack    console.log(user.role.name); // admin    user.name = 'mark';    user.role.name = 'qa';    console.log(user.name); // jack    console.log(user.role.name); // qa

可以看到,user的role属性是个对象,而role的name属性仍然可以修改,想要解决这种情况,需要将对象的属性也冻结。

let role = {name: 'admin'};    const user = {        name: 'jack',        role: role    };    let constantize = (obj) => {        Object.freeze(obj);        Object.keys(obj).forEach((key, value) => {            if (typeof obj[key] === 'object') {                constantize(obj[key]);            }        });    };    constantize(user);    console.log(user.name); // jack    console.log(user.role.name); // admin    user.name = "mark";    user.role.name = "qa";    console.log(user.name); // jack    console.log(user.role.name); // admin

上面代码中,constantize是一个将对象彻底冻结的函数,调用该函数后,则user对象就彻底冻结了。

转载于:https://my.oschina.net/u/2450666/blog/896462

你可能感兴趣的文章
Default Constructor 的建构操作
查看>>
函数中的不定长参数研究 *and**
查看>>
hive如何执行mr
查看>>
测试及等等
查看>>
通过Python来操作kylin
查看>>
模板 数据结构
查看>>
【Search a 2D Matrix】cpp
查看>>
POJ 1741 Tree(树的点分治,入门题)
查看>>
Opencv3.1.0 & Win10/Win7 64位 contrib编译
查看>>
黄聪:FFmpeg 使用指南
查看>>
C#:CodeSmith根据数据库中的表创建C#数据模型Model + 因为没有钱买正版,所以附加自己写的小代码...
查看>>
乐视4.14硬件免费日de用户体验
查看>>
C — 对C语言的认识
查看>>
linkin大话数据结构--Set
查看>>
$.each 和$(selector).each()的区别
查看>>
JSON格式自动解析遇到的调用方法问题.fromJson() ..readValue()
查看>>
Crystal Reports for Visual Studio 2015 安装
查看>>
iOS UI 15 网络编程下载 图片 音乐 大文件 视频 get/ post方法
查看>>
linux文件系统 - 初始化(二)
查看>>
Python的可视化图表工具集
查看>>