在javascript中,我们都知道使用var来声明变量。javascript是函数级作用域,函数内可以访问函数外的变量,函数外不能访问函数内的变量。

函数级作用域会导致一些问题就是某些代码块内的变量会在全局范围内有效,这我们是非常熟悉的:

 for (var i = 0; i < 10; i++) {
console.log(i); // 0,1,2...,9
}
console.log(i); // if(true){
var s = 20;
}
console.log(s); //

在es6中增加了let(变量)和const(常量)来声明变量,使用的是块级作用域,变量声明只在代码块内有效:

 for (let i = 0; i < 10; i++) {
console.log(i); // 0,1,2...,9
}
console.log(i); //ReferenceError: i is not defined if(true){
let s = 20;
}
console.log(s); //ReferenceError: s is not defined

我们最常遇到的循环事件绑定i产生的闭包问题,是因为i绑定在全局,每次访问都会取到全局的i的值,所以访问哪个元素,得到的i都是循环体最后一轮的i。我们通常的解决办法是借助IIFE。在es6中let定义的i只在循环体内有效,所以每次循环i都是一个新的变量,于是会产生正常的输出:

 //使用var
var arr1 = [];
for (var i = 0; i < 10; i++) {
arr1[i] = function() {
console.log(i);
}
} arr1[5](); //
arr1[8](); // //使用let
var arr2 = [];
for (let i = 0; i < 10; i++) {
arr2[i] = function() {
console.log(i);
}
} arr2[5](); //
arr2[8](); //

变量提升:

在es5中var定义的变量存在变量提升,es6中使用的let不存在变量提升:

 console.log(i);
var i = 10; // console.log(s);
let s = 20; //ReferenceError: can't access lexical declaration `s' before initialization

函数提升:

es5中无论if语句是否执行,在if语句内的函数声明都会提升到当前的作用域的顶部而得到执行,es6支持块级作用域,无论是否进入if,内部的函数都不会影响到外部的函数

严格模式下函数声明只能在顶层环境和函数体内,不能if或者循环体内进行函数声明

 //es5环境
function f(){
console.log('outside');
}
if(true){
function f(){
console.log('inside');
}
} f(); //inside //es6环境
function d(){
console.log('outside');
}
if(true){
function d(){
console.log('inside');
}
} d(); //outside

每个代码块中即同一个作用域中,每个变量只能使用let定义一次,使用var重复定义会进行覆盖,但是使用let重复定义会报错,不同代码块可以重复定义:

 let i = 10;

 if(true){
let i = 20;
console.log(i); //
let i = 50; //redeclaration of let i
console.log(i);
}

暂时性死区:

在代码块内,使用let声明变量之前,该变量都不可用,即是变量在使用赋值之前需要先进行声明,每个代码块会进行变量绑定,以确定变量属于哪个环境,在绑定之前进行变量的操作都是非法的:

 let i = 10;

 if(true){
i = 50; //ReferenceError
let i = 20;
console.log(i);
}
//因为在if中声明了i,i绑定了if的环境,所以在if的i声明之前,i都不可用,导致i=50报错

IIFE有一个重要的作用是封装变量,避免变量泄漏到全局,块级作用域的出现,其实就使得IIFE不再必要了:

 ~function(){
if(true){
var i = 10;
}
}()
console.log(i); //ReferenceError: i is not defined if(true){
let s = 20;
} console.log(s); //ReferenceError: s is not defined

let和const的区别:

let声明变量,值可以改变。const声明常量,值不可改变(使用const时,常量最好使用大写)

其他的属性let与const一致

 let a = 10;
a = 20;
console.log(a); // const B = 30;
B = 40; //TypeError: invalid assignment to const `b'
console.log(B);

const只保证常量名指向的地址不变,并不能保证地址的数据不变,如果想吧对象冻结数据不可改变,可使用Object.freeze(obj)

 const a = {};
a.name = 'gary';
console.log(a.name); //gary const b = Object.freeze({});
b.name = 'bob';
console.log(b.name); //undefined

在es5中我们都知道,在全局定义变量其实就是等于在全局对象设置属性,全局对象属性与全局变量是等价的。全局变量的赋值和全局属性的赋值是同一件事

在es6中修改可这一规定,使用let和const和class声明的全局变量与全局对象不等价

 var a = 10;
console.log(a === window.a); //true let b = 20;
console.log(b === window.b); //false

es6之let和const的更多相关文章

  1. es6(一):es6介绍以及let,const

    es是js的规范,而js是具体实现 将es6转化为es5代码工具:运用的多的是babel 在线转换地址:babel,traceur(属于谷歌)   1.let申明变量:let其实可以完全取代var,并 ...

  2. ES6(let 和 const)

    一项新技术的出现肯定是为了解决一些问题,那么ES6的出现主要是解决了哪些问题?它的出现给我们带来了什么便利?当它没有出现的时候,某些问题怎么处理?ES6的方法和以前的方法比较又有什么不同呢?根据提出的 ...

  3. ES6 之 let和const命令 Symbol Promise对象

    ECMAScript 6入门 ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了. (2016年6月,发布了小幅修订的<ECMASc ...

  4. es6之let和const命令的一些笔记

    let和const命令 let命令 基本用法 let命令用来声明变量,声明的变量只在命令所在的代码块内有效.for循环中很适合使用let命令. 有必要理解的例子: var a = []; for (v ...

  5. JavaScript ES6 的let和const

    1 作用域和提升 1.1 作用域(Scope) 某个变量名或者函数名,在某个程序片段中是否可见或者可访问,如果是,那么这个程序片段就是这个变量名或者函数名的作用域.比如: var name = &qu ...

  6. ES6中var/let/const的区别

    let的含义及let与var的区别: let 声明的变量只在它所在的代码块有效: 如下: for (let i = 0; i < 10; i++) { console.log(i); } con ...

  7. ES6系列之let/const及块级作用域

    本系列是在平时阅读.学习.实际项目中有关于es6中的新特性.用发的简单总结,目的是记录以备日后温习:本系列预计包含let/const.箭头函数.解构.常用新增方法.Symbol.Set&Map ...

  8. ES6 中 let and const

    let 和 const 命令 let 命令 基本用法 ES6 新增了let命令,用来声明变量.它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效. { let a = 10; v ...

  9. ES6中let与const命令详解

    阮一峰ES6入门 let 作用域 let命令用来声明变量,但声明的变量只在let命令所在的代码块内有效. { let a = 10; var b = 1; } a // ReferenceError: ...

随机推荐

  1. C#与C++的发展历程第三 - C#5.0异步编程巅峰

    系列文章目录 1. C#与C++的发展历程第一 - 由C#3.0起 2. C#与C++的发展历程第二 - C#4.0再接再厉 3. C#与C++的发展历程第三 - C#5.0异步编程的巅峰 C#5.0 ...

  2. C# 破解 Reflector8.5

    一.分析 破解.net .dll,可以使用reflector,但官方提供的reflector是需要购买的,因此,破解reflector势在必行. 二.破解Reflector具体步骤 下面为详细的破解步 ...

  3. 伪共享(false sharing),并发编程无声的性能杀手

    在并发编程过程中,我们大部分的焦点都放在如何控制共享变量的访问控制上(代码层面),但是很少人会关注系统硬件及 JVM 底层相关的影响因素.前段时间学习了一个牛X的高性能异步处理框架 Disruptor ...

  4. XML技术之DOM4J解析器

    由于DOM技术的解析,存在很多缺陷,比如内存溢出,解析速度慢等问题,所以就出现了DOM4J解析技术,DOM4J技术的出现大大改进了DOM解析技术的缺陷. 使用DOM4J技术解析XML文件的步骤? pu ...

  5. Tesseract-OCR字符识别简介

    OCR(Optical Character Recognition):光学字符识别,是指对图片文件中的文字进行分析识别,获取的过程.Tesseract:开源的OCR识别引擎,初期Tesseract引擎 ...

  6. 来吧,HTML5之一些注意事项

    1.说什么是HTML HTML是一种超文本标记语言(Hyper Text Markup Language), 标记语言是一套标记标签(markup tag),用来描述网页的非编程语言. 2.标签特性: ...

  7. pt-heartbeat

    pt-heartbeat是用来监测主从延迟的情况的,众所周知,传统的通过show slave status\G命令中的Seconds_Behind_Master值来判断主从延迟并不靠谱. pt-hea ...

  8. Android 工具-adb

    Android 工具-adb 版权声明:本文为博主原创文章,未经博主允许不得转载. Android 开发中, adb 是开发者经常使用的工具,是 Android 开发者必须掌握的. Android D ...

  9. NPM如何更新到最新版

    参考文章--npm更新到最新版本的方法 其实我们可以这样,随便新建一个文件夹例如:F:\test.按着"shift"键,右键该文件夹,选择"在此处打开命令窗口(W)&qu ...

  10. Android之数据存储的五种方法

    1.Android数据存储的五种方法 (1)SharedPreferences数据存储 详情介绍:http://www.cnblogs.com/zhangmiao14/p/6201900.html 优 ...