es6之let和const
在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的更多相关文章
- es6(一):es6介绍以及let,const
es是js的规范,而js是具体实现 将es6转化为es5代码工具:运用的多的是babel 在线转换地址:babel,traceur(属于谷歌) 1.let申明变量:let其实可以完全取代var,并 ...
- ES6(let 和 const)
一项新技术的出现肯定是为了解决一些问题,那么ES6的出现主要是解决了哪些问题?它的出现给我们带来了什么便利?当它没有出现的时候,某些问题怎么处理?ES6的方法和以前的方法比较又有什么不同呢?根据提出的 ...
- ES6 之 let和const命令 Symbol Promise对象
ECMAScript 6入门 ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了. (2016年6月,发布了小幅修订的<ECMASc ...
- es6之let和const命令的一些笔记
let和const命令 let命令 基本用法 let命令用来声明变量,声明的变量只在命令所在的代码块内有效.for循环中很适合使用let命令. 有必要理解的例子: var a = []; for (v ...
- JavaScript ES6 的let和const
1 作用域和提升 1.1 作用域(Scope) 某个变量名或者函数名,在某个程序片段中是否可见或者可访问,如果是,那么这个程序片段就是这个变量名或者函数名的作用域.比如: var name = &qu ...
- ES6中var/let/const的区别
let的含义及let与var的区别: let 声明的变量只在它所在的代码块有效: 如下: for (let i = 0; i < 10; i++) { console.log(i); } con ...
- ES6系列之let/const及块级作用域
本系列是在平时阅读.学习.实际项目中有关于es6中的新特性.用发的简单总结,目的是记录以备日后温习:本系列预计包含let/const.箭头函数.解构.常用新增方法.Symbol.Set&Map ...
- ES6 中 let and const
let 和 const 命令 let 命令 基本用法 ES6 新增了let命令,用来声明变量.它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效. { let a = 10; v ...
- ES6中let与const命令详解
阮一峰ES6入门 let 作用域 let命令用来声明变量,但声明的变量只在let命令所在的代码块内有效. { let a = 10; var b = 1; } a // ReferenceError: ...
随机推荐
- SQL Server2014 SP2新增的数据库克隆功能
SQL Server2014 SP2新增的数据库克隆功能 创建测试库 --创建测试数据库 create database testtest use testtest go --创建表 )) --插入数 ...
- JAVA回调机制(CallBack)详解
序言 最近学习java,接触到了回调机制(CallBack).初识时感觉比较混乱,而且在网上搜索到的相关的讲解,要么一言带过,要么说的比较单纯的像是给CallBack做了一个定义.当然了,我在理解了回 ...
- app开发外包注意事项,2017最新资讯
我们见过很多创业者,栽在这app外包上.很多创业者对于app外包这件事情不是特别重视,以为将事情交给app外包公司就完事了,实际上不是的.无论是从选择app外包公司还是签订合同.售后维护等各方面都有许 ...
- 2D、3D形变
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px Monaco; color: #a5b2b9 } span.Apple-tab-span { ...
- 使用python抓取婚恋网用户数据并用决策树生成自己择偶观
最近在看<机器学习实战>的时候萌生了一个想法,自己去网上爬一些数据按照书上的方法处理一下,不仅可以加深自己对书本的理解,顺便还可以在github拉拉人气.刚好在看决策树这一章,书里面的理论 ...
- angular2系列教程(十)两种启动方法、两个路由服务、引用类型和单例模式的妙用
今天我们要讲的是ng2的路由系统. 例子
- ZKWeb网页框架1.4正式发布
本次更新的内容有 添加更快的批量操作函数 添加IDatabaseContext.FastBatchSave 添加IDatabaseContext.FastBatchDelete 注意这些函数不会触发注 ...
- 【WPF】日常笔记
本文专用于记录WPF开发中的小细节,作为备忘录使用. 1. 关于绑定: Text ="{Binding AnchorageValue,Mode=TwoWay,UpdateSourceTrig ...
- maven 快照
大型应用软件一般由多个模块组成,一般它是多个团队开发同一个应用程序的不同模块,这是比较常见的场景.例如,一个团队正在对应用程序的应用程序,用户界面项目(app-ui.jar:1.0) 的前端进行开发, ...
- grep 查找bash脚本中的注释代码
出于安全性的考虑,不建议在bash脚本中注释掉不使用的代码.也就是说如果某段代码不使用了,那么应该删除掉,而不是简单地注释掉.假如你突然意识到这一点,而以前并没有遵从这个原则,现在需要找出脚本中的注释 ...