let 和 const

let 声明

  (一)基本用法

    let 声明的变量只在块级作用域内有效,出了该块则报错,最常见且适合的地方在 for 循环中:

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

  上面的 i 通过 var 方式声明,(循环次数内)全局有效且只有一个,故每次循环结束后, i 的值会被更新,从而导致在完成所有循环后, a 数组中所有的成员中的 i 均指向最后一次更新的值, 即 10,而使用 let 声明:

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

在每次循环时,该次循环体(代码块)中的 i 只对当前代码块有效,简单而言即:每次循环的 i 相当于一个新的变量,故最终结果是 6 。

  (二)var 的变量提升

    先看一个例子:

console.log(foo); // 输出undefined
var foo = 2;

    按照正常的逻辑,执行 console 时,变量 foo 在内存中并不存在,但是此时会输出 undefined(未赋值) 错误,这就是 var 声明的变量提升:脚本运行时,变量已经存在,但是没有值,最终输出 undefined。使用 let 声明可以避免变量提升。

  (三)暂时性死区

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

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

    如上例所示,在 let 命令之前, tmp 变量都不可用, 这块区域都属于 tmp 的 “死区”,语法上称这种现象为 “暂时性死区”。

  注意:1.使用 let 命令时,typeof 不在是一个百分百安全操作;

     2.一个比较隐蔽的死区:

function bar(x = y, y = 2) {
return [x, y];
} bar(); // 报错

  调用 bar() 报错的原因在于 x = y 时,y 并没有声明,属于 “死区”,故报错。解决办法是将函数中参数位置对调即可。

  同理:

// 不报错
var x = x; // 报错
let x = x;
// ReferenceError: x is not defined

  总之:暂时性锁区的本质是,只要一进入当前作用域,所要使用的变量就已经存在,但是处于不可获取的状态,只有等到声明语句出现,才可以获取和使用。

  (四)块级作用域

  es 5 只有全局和函数作用域两种,接下来看两个 es5 的例子:

  1.内层变量覆盖外层变量

var tmp = new Date();

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

  在 fun f() 中,因为存在 var 指令,故可以说在 f() 中就会存在变量提升的现象(而且优先级貌似蛮高的), 所以这就会导致 console undefined 错误,而不是 console 时间;

  2.用来计数的循环变量泄露成全局变量:

var s = 'hello';

for (var i = 0; i < s.length; i++) {
console.log(s[i]);
} console.log(i); // 5

  上例可以看出,在循环结束后,作为控制循环的 i 变量并没有消失,这样就很容易泄露,可能会被恶意利用。

  而 let 的使用为 es 6 新増了块级作用域。

const 声明

  效果跟 java 中的 static final 差不多;

  需要注意:   

    1.const 的变量声明时必须赋值,否则报错;

    2.const 的变量一旦声明,其值只读,不可改变;

    3.const 的作用域与 let 相同: 只在声明所在的块级作用域内有效;

    4.const 的变量不存在变量提升现象,同样存在暂时性死区;

    5.const 的变量,不可重复声明;

    6.关于引用类型的对象,一个例子:

const a = [];
a.push('Hello'); // 可执行
a.length = 0; // 可执行
a = ['Dave']; // 报错

      常量 a 中存储了一个数组对象的地址,然后这个数组对象中的内容是可变的,但是,最后一行很明显是把一个新的数组对象的地址赋值给 a,这就导致了报错。

ES 6 系列 - 变量声明的更多相关文章

  1. es6 快速入门 系列 —— 变量声明:let和const

    其他章节请看: es6 快速入门 系列 变量声明:let和const 试图解决的问题 经典的 var 声明让人迷惑 function demo1(v){ if(v){ var color='red' ...

  2. es6系列-变量声明

    es6系列所有文章都是阅读阮一峰老师的<ES6标准入门>(第2版)所做的读书笔记.方便日后查阅相关基础知识. git地址: https://github.com/rainnaZR/es6- ...

  3. Nodejs与ES6系列1:变量声明

    1.声明变量 在JS当中一个变量的作用域(scope)是程序中定义这个变量的区域.变量分为两类,全局(global)的和局部的.其中全局变量的作用域是全局性的,即在JavaScript代码中,它处处都 ...

  4. ES6系列之变量声明let const

    ES6也出来好久了,最近闲来无事就想着吧es6做一个系统的总结,巩固自己的知识,丰富一下博客. 为什么叫ES6 实际上是ECMA的一个打的标准,这个标准是在2015年6月发布的,正式的名字实际是es2 ...

  5. 详解变量声明加 var 和不加 var 的区别

    在全局作用域中声明变量加 var 关键字和不加 var ,js 引擎都会将这个变量声明为全局变量,在实际运行时,两种声明方式的变量的行为也是几乎一致的.但是在全局作用域下是否声明一个变量的 时候加va ...

  6. ES 6 系列 - 赋值的新方式:解构赋值

    变量的解构赋值 es 6 允许按照一定的模式,从数组和对象中提取值,然后对变量进行赋值,这被称之为解构: 一.数组的解构赋值 最基本写法: let [a, b, c] = [1, 2, 3]; a / ...

  7. Js 变量声明提升和函数声明提升

    Js代码分为两个阶段:编译阶段和执行阶段 Js代码的编译阶段会找到所有的声明,并用合适的作用域将它们关联起来,这是词法作用域的核心内容 包括变量声明(var a)和函数声明(function a(){ ...

  8. js 碎片整理(变量声明,函数作用域)

    1.变量声明: 在非严格模式下,函数可以对未声明的变量赋值,而这样赋值的结果就是该变量就会变成全局变量. (function(){ var a = 1; })(); console.log(a) ; ...

  9. TypeScript 素描-变量声明

    博文读自 TypeScript 官方文档而来,不具有学习性,仅是本人学习时记录以供日后翻阅 ,有学习TypeScript的朋友还请去看更为详细的官方文档 /* 变量声明在之前的js中一直是使用var关 ...

随机推荐

  1. IBus prior to 15.11 may cause input problems. See IDEA-78860 for details.

    启动 PyCharm 2017.2, 遇到问题: IBus prior to 15.11 may cause input problems. See IDEA-78860 for details. 解 ...

  2. 洛谷题解 P1138 【第k小整数】

    蒟蒻发题解了 说明:此题我用的方法为桶排(我翻了翻有人用了桶排只不过很难看出来,可能有些重复的,这个题只是作为一个专门的桶排来讲解吧) (不会算抄袭吧 ‘QWaWQ’) 简单来说(会的人跳过就行): ...

  3. mongo中游标

    1.手动循环访问游标 mongo中我们常用的查询方式db.collection.find()方法其实返回的就是游标,只不过我们并未给返回的游标分配变量,我们所看到的的查询数据也就是游标自动迭代得出的( ...

  4. 从零开始搭建django前后端分离项目 系列四(实战之实时进度)

    本项目实现了任务执行的实时进度查询 实现方式 前端websocket + 后端websocket + 后端redis订阅/发布 实现原理 任务执行后,假设用变量num标记任务执行的进度,然后将num发 ...

  5. Chrome开发者工具应对页面跳转页面点击事件等实用干货

    1.如何解决页面跳转 打开Preserve log即可 禁用页面缓存在右边的disable cache 2.如何监听页面点击 重要的是举一反三,看不懂英文去翻译!Mouse鼠标,click点击,,,, ...

  6. Python股票分析系列——数据整合.p7

    欢迎来到Python for Finance教程系列的第7部分. 在之前的教程中,我们为整个标准普尔500强公司抓取了雅虎财经数据. 在本教程中,我们将把这些数据组合到一个DataFrame中. 到此 ...

  7. 【开源】Westore Cloud 发布- 没后端没SQL没DBA,只需 javascript 开发云端小程序

    Westore Cloud - 隐形云,NoBackEnd,NoSql,HiddenDB 好的设计便是感觉不到设计的存在 开发小程序,但是:没有后端!没有运维!没有 DBA!没有域名!没有证书!没有钱 ...

  8. Dockerfile cnetos7_nginx1.15.10

    FROM centos:7 MAINTAINER yuyongxr yuyongxr@gmail.com LABEL Discription="centos7+nginx1.15.10&qu ...

  9. H5 28-优先级之权重问题

    28-优先级之权重问题 我是段落 <!DOCTYPE html> <html lang="en"> <head> <meta charse ...

  10. 广州商学院16级软工一班&二班-第二次作业成绩

    作业地址 https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/2097 https://edu.cnblogs.com/campus/gzc ...