在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. 【大型网站技术实践】初级篇:借助Nginx搭建反向代理服务器

    一.反向代理:Web服务器的“经纪人” 1.1 反向代理初印象 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从 ...

  2. JavaScript权威指南 - 对象

    JavaScript对象可以看作是属性的无序集合,每个属性就是一个键值对,可增可删. JavaScript中的所有事物都是对象:字符串.数字.数组.日期,等等. JavaScript对象除了可以保持自 ...

  3. 谈谈一些有趣的CSS题目(九)-- 巧妙的实现 CSS 斜线

    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...

  4. 主成分分析(PCA)原理总结

    主成分分析(Principal components analysis,以下简称PCA)是最重要的降维方法之一.在数据压缩消除冗余和数据噪音消除等领域都有广泛的应用.一般我们提到降维最容易想到的算法就 ...

  5. Spring的数据库开发

                                Spring JDBC框架操作mysql数据库 Spring中的JDBC为我们省去连接和关闭数据库的代码,我们着重关注对数据库的操作.Sprin ...

  6. C++标准库实现WAV文件读写

    在上一篇文章RIFF和WAVE音频文件格式中对WAV的文件格式做了介绍,本文将使用标准C++库实现对数据为PCM格式的WAV文件的读写操作,只使用标准C++库函数,不依赖于其他的库. WAV文件结构 ...

  7. Python 正则表达式入门(中级篇)

    Python 正则表达式入门(中级篇) 初级篇链接:http://www.cnblogs.com/chuxiuhong/p/5885073.html 上一篇我们说在这一篇里,我们会介绍子表达式,向前向 ...

  8. spring无法读取properties文件数据

    只讲述异常点,关于怎么配置文件,这里不做说明.   1. controller中无法读取config.properties文件 controller中注入的@Value配置是从servlet-cont ...

  9. hibernate的基本xml文件配置

    需要导入基本的包hibernate下的bin下的required和同bin下optional里的c3p0包下的所有jar文件,当然要导入mysql的驱动包了.下面需要注意的是hibernate的版本就 ...

  10. .Net中的AOP系列之《间接调用——拦截方法》

    返回<.Net中的AOP>系列学习总目录 本篇目录 方法拦截 PostSharp方法拦截 Castle DynamicProxy方法拦截 现实案例--数据事务 现实案例--线程 .Net线 ...