let 和 const 命令


学习资料:ECMAScript 6 入门

let

  • 所声明的变量,只在let命令所在的代码块内有效。用途:循环计数器。

如果使用var,只有一个全局变量i:

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

如果使用let,声明的变量仅在块级作用域内有效,JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算:

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

设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域:

    for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
  • 不存在变量提升

let所声明的变量一定要在声明后使用:

    // var 的情况
console.log(foo); // 输出undefined
var foo = 2; // let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;
  • 暂时性死区

只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。所以需要先声明再使用:

    var tmp = 123;

    if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
} if (true) {
// TDZ开始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError let tmp; // TDZ结束
console.log(tmp); // undefined tmp = 123;
console.log(tmp); // 123
}

隐蔽的死区:

    function bar(x = y, y = 2) {
return [x, y];
} bar(); // 报错
  • 不允许重复声明

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

    // 报错
function func() {
let a = 10;
var a = 1;
} // 报错
function func() {
let a = 10;
let a = 1;
} function func(arg) {
let arg; // 报错
} function func(arg) {
{
let arg; // 不报错
}
}

块级作用域

  • ES5中没有块级作用域

ES5中没有块级作用域,内层变量可能会覆盖外层变量:

    var tmp = new Date();

    function f() {
console.log(tmp);
if (false) {
var tmp = 'hello world';
}
} f(); // undefined

ES5中没有块级作用域,用来计数的循环变量泄露为全局变量:

    var s = 'hello';

    for (var i = 0; i < s.length; i++) {
console.log(s[i]);
} console.log(i); // 5
  • ES6 的块级作用域

      function f1() {
    let n = 5;
    if (true) {
    let n = 10;
    }
    console.log(n); // 5
    }
  • 块级作用域与函数声明

ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。但在浏览器的 ES6 环境中,块级作用域内声明的函数,行为类似于var声明的变量。

    // 浏览器的 ES6 环境
function f() { console.log('I am outside!'); } (function () {
if (false) {
// 重复声明一次函数f
function f() { console.log('I am inside!'); }
} f();
}());
// Uncaught TypeError: f is not a function

考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。

    // 函数声明语句
{
let a = 'secret';
function f() {
return a;
}
} // 函数表达式
{
let a = 'secret';
let f = function () {
return a;
};
}

ES6 的块级作用域允许声明函数的规则,只在使用大括号的情况下成立,如果没有使用大括号,就会报错。

    // 不报错
'use strict';
if (true) {
function f() {}
} // 报错
'use strict';
if (true)
function f() {}

const 命令

const声明一个只读的常量。一旦声明,常量的值就不能改变。

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

与let类似,只在声明所在的块级作用域内有效。声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。不可重复声明。

const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。

如果真的想将对象冻结,应该使用Object.freeze方法。

    const foo = Object.freeze({});

    // 常规模式时,下面一行不起作用;
// 严格模式时,该行会报错
foo.prop = 123;

除了将对象本身冻结,对象的属性也应该冻结。下面是一个将对象彻底冻结的函数。

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

顶层对象的属性

var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。

垫片库system.global可以在所有环境拿到global。

    // CommonJS 的写法
var global = require('system.global')(); // ES6 模块的写法
import getGlobal from 'system.global';
const global = getGlobal();

ES6 学习笔记 - let和const的更多相关文章

  1. ES6学习笔记<一> let const class extends super

    学习参考地址1  学习参考地址2 ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准.因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015:也 ...

  2. es6学习笔记--let和const

    今天学习了es6中的let和const命令,借此整理一下笔记. let : let 和 var 的声明方式一样,但有 var 比不上的优点.下面用 var 和 let 的例子来加深对 let 的理解. ...

  3. ES6学习笔记(let,const,变量的解构赋值)

    1.let: ; i < 3; i++) { let i = 'abc'; console.log(i); } // abc // abc // abc 不存在变量提升,它所声明的变量一定要在声 ...

  4. ES6学习笔记<五> Module的操作——import、export、as

    import export 这两个家伙对应的就是es6自己的 module功能. 我们之前写的Javascript一直都没有模块化的体系,无法将一个庞大的js工程拆分成一个个功能相对独立但相互依赖的小 ...

  5. ES6学习笔记<四> default、rest、Multi-line Strings

    default 参数默认值 在实际开发 有时需要给一些参数默认值. 在ES6之前一般都这么处理参数默认值 function add(val_1,val_2){ val_1 = val_1 || 10; ...

  6. ES6学习笔记<三> 生成器函数与yield

    为什么要把这个内容拿出来单独做一篇学习笔记? 生成器函数比较重要,相对不是很容易理解,单独做一篇笔记详细聊一聊生成器函数. 标题为什么是生成器函数与yield? 生成器函数类似其他服务器端语音中的接口 ...

  7. ES6学习笔记<二>arrow functions 箭头函数、template string、destructuring

    接着上一篇的说. arrow functions 箭头函数 => 更便捷的函数声明 document.getElementById("click_1").onclick = ...

  8. ES6学习笔记(一)——let和const

    1.ES6学习之let.const (1).var.let.const 变(常)量声明 ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景. 在ES6中let就诞生了,实际上它 ...

  9. es6学习笔记-class之一概念

    前段时间复习了面向对象这一部分,其中提到在es6之前,Javasript是没有类的概念的,只从es6之后出现了类的概念和继承.于是乎,花时间学习一下class. 简介 JavaScript 语言中,生 ...

随机推荐

  1. 洛谷 P4057 [Code+#1]晨跑

    P4057 [Code+#1]晨跑 题目描述 “无体育,不清华”.“每天锻炼一小时,健康工作五十年,幸福生活一辈子” 在清华,体育运动绝对是同学们生活中不可或缺的一部分.为了响应学校的号召,模范好学生 ...

  2. Ubuntu 16.04在搭建Redis Cluster搭建时,使用gem install redis时出现:ERROR: While executing gem ... (Gem::FilePermissionError) You don't have write permissions for the /var/lib/gems/2.3.0 directory.

    注意:千万不要使用sudo来执行gem install redis. 解决方法: sudo apt-get update sudo apt-get install git-core curl zlib ...

  3. 剑指Offer - 两个链表第一个公共节点

    https://www.nowcoder.com/practice/6ab1d9a29e88450685099d45c9e31e46?tpId=13&tqId=11189&tPage= ...

  4. tornado的http服务器实现

    使用tornado实现的一个简单http服务器:只需要定义自己的处理方法,其他的东西全部交给tornado完成. #coding:utf-8 import tornado.httpserver imp ...

  5. Ckeditor通过Ajax更新数据

    之前在表单中对ckeditor的赋值就直接是 $("#theadEditor").val(result); 而如今我想通过点击不同选项来使用Ajax在后台訪问数据.对ckedito ...

  6. mybatis之if else语句

    最近项目中遇到一个相同表设计,但是表名不同的sql语句操作. 在遇到这样的情况时候可以用一下方式: <choose> <when test=""> //.. ...

  7. java struts jxl 导入导出Excel(无模板)

    jar包: import javax.servlet.http.HttpServletResponse; import java.io.OutputStream; import java.io.Fil ...

  8. git log 常用选项

    git log 常用选项 -p 按补丁格式显示每个更新之间的差异. jiqing@Ubuntu:/home/wwwroot/default/5hao/sheep$ git log -p commit ...

  9. 控件CListCtr详解

    1.CListCtrl控件 CListCtrl控件在数据库编程中是用得比较多的控件之一,也是Window控件中较难掌握的一个控件.他可以有四显示方式,Report.List.Icon.SmallIco ...

  10. URAL 1057 数位dp

    题目传送门http://acm.timus.ru/problem.aspx?space=1&num=1057 最近在学习数位dp,具体姿势可以参照这篇论文:http://wenku.baidu ...