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. IDEA+Maven+web项目

    用IDEA创建一个简单的Maven web项目:https://blog.csdn.net/sinat_34596644/article/details/52891274

  2. 初学Python——软件目录结构规范

    为什么要设计好目录结构? 可读性高: 不熟悉这个项目的代码的人,一眼就能看懂目录结构,知道程序启动脚本是哪个,测试目录在哪儿,配置文件在哪儿等等.从而非常快速的了解这个项目. 可维护性高: 定义好组织 ...

  3. 深入理解koa中的co源码

    阅读目录 一:理解Generator 二:理解js函数柯里化 三:理解Thunk函数 四:理解CO源码 回到顶部 一:理解Generator 在看co源码之前,我们先来理解下Generator函数.G ...

  4. 【C#复习总结】垃圾回收机制(GC)1

    摘要:今天我们漫谈C#中的垃圾回收机制,本文将从垃圾回收机制的原理讲起,希望对大家有所帮助. GC的前世与今生 虽然本文是以.NET作为目标来讲述GC,但是GC的概念并非才诞生不久.早在1958年,由 ...

  5. 官宣 ! 52abp_Pro版本低调上线

    上线了 官宣!官宣!官宣! 重要的事情说三次. 是的,你没有看错 https://www.52abp.com/ 的官方企业模板:52abp-pro已经正式上线. 至此52abp.com的官方网站就算告 ...

  6. [转]WINDOWS服务器安全加固实战(WINDOWS SERVER 2008 R2和WINDOWS SERVER 2012)

    主机安全 启用防火墙 阿里云windows Server 2008 R2默认居然没有启用防火墙.2012可能也是这样的,不过这个一定要检查! 补丁更新 启用windows更新服务,设置为自动更新状态, ...

  7. lambda函数

    1.lambda函数是语法简短的匿名函数 2.lambda函数可以接受一个或多个参数 3.lambda函数只能有一个表达式 4.一般用于非重用的代码块 1)g = lambda x : x**2 g( ...

  8. 网络拓扑自动发掘之三层设备惯用的SNMP OID的含义

    原文地址:https://blog.csdn.net/maty_wang/article/details/81305070 1. ipNetToMediaIfIndex Name/OID: ipNet ...

  9. 如何在Github中删除已有仓库或文件

    一.删除已有仓库如果我们想要删除Github中没有用的仓库,应该如何去做呢? 进入到我们需要删除的仓库里面,找到“settings”即仓库设置: 然后,在仓库设置里拉到最底部,找到“Danger Zo ...

  10. vue 渲染函数&jsx

    前端更新状态,更新视图,所以性能问题主要由Dom操作引起的,而js解析编译dom渲染就要快得多,  所把要js和html混写. vue 的动态js操作 html  方法:reader函数: vue  ...