function show( flag ){
console.log( a );
if( flag ){
var a = 'ghostwu';
return a;
} else {
console.log( a );
return null;
}
}

我们从es5的变量提升开始说起, 由于变量提升的原因, 上述程序, 在第2行和第7行都能访问到a的值, 只不过是undefined, 如果你不熟悉javascript这种变量的预解释机制,可能会认为第2行和第7行会报错, 只有flag为true的时候,变量a才声明了, 其实javascript在词法解释的时候,会把上述代码解释成下面的样子:

        function show( flag ){
var a;
console.log( a );
if( flag ){
a = 'ghostwu';
return a;
} else {
console.log( a );
return null;
}
}

这种机制,在项目中经常误导程序员,哪怕是资深的前端程序员,不小心也容易入坑, 于是ES6引入了块级作用域来强化对变量生命周期的控制.

什么是块级作用域?

1,函数内部

2,块中( 通常指的是一对花括号之间)

es6中使用新的关键词 let 来定义变量, 为块级作用域,上例,如果改成let声明

     function show( flag ){
console.log( a );
if( flag ){
let a = 'ghostwu';
return a;
}else {
console.log( a );
return nul;
}
}

由于let是块级作用域,不会像var一样 产生变量提升, 所以,第2行和第7行 这个时候报错( a is not defined )

只有在flag为true的情况,a会被定义, 而且访问范围在第3行和第6行的大括号之间, 超出这个范围,就访问不到a, 这就是块级作用域

let都有哪些特性呢?

在同一个作用域下,let不能重复定义两个同名的标识符

在不同的作用域下,可以使用同名的标识符

 var a = 'ghostwu';
let a = 'ghostwu2';
 let a = 'ghostwu';
let a = 'ghostwu2';

以上两种方式,都会报重定义错误(Identifier 'a' has already been declared)

         let a = 10;
if( a ){
let a = 100;
console.log( a ); //
}
console.log( a ); //10

以上这种方式,不会报错,因为是两个不同的作用域

let的经典应用

在4个按钮中,获取当前被点击按钮的索引

      <script>
window.onload = function(){
var aInput = document.querySelectorAll("input");
for( var i = 0; i < aInput.length; i++ ){
aInput[i].onclick = function(){
alert( i );
}
}
}
</script> <input type="button" value="按钮1">
<input type="button" value="按钮2">
<input type="button" value="按钮3">
<input type="button" value="按钮4">

如果,我们用上面的方法做, 每个按钮点击之后 i 都是4, 因为4个按钮绑定完事件之后,i的值就变成了4, 下次点击按钮的时候,所有的都是4, 因为 i = 4 是共享的

通常,我们会在每个按钮上,加一个自定义索引 绑定 对应的 i 值,再借助this关键字,就可以如愿以偿,如下:

         window.onload = function(){
var aInput = document.querySelectorAll("input");
for( var i = 0; i < aInput.length; i++ ){
aInput[i].index = i;
aInput[i].onclick = function(){
alert(this.index);
}
}
}

还有另一种方法,就是借用立即表达式+闭包的形式, 如下:

         window.onload = function(){
var aInput = document.querySelectorAll("input");
for( var i = 0; i < aInput.length; i++ ){
aInput[i].onclick = (function( j ){
return function(){
alert( j );
}
})( i );
}
}

而采用let关键字, 利用块级作用域的特性,就可以轻松达到目的

         window.onload = function(){
var aInput = document.querySelectorAll("input");
for( let i = 0; i < aInput.length; i++ ){
aInput[i].onclick = function(){
alert( i );
};
}
}

var在全局作用域下,会把属性绑定到window上,从而可能产生覆盖属性的隐患,而let关键字只是会遮蔽它,并不会覆盖window上的同名属性

         var a = 10;
console.log( a ); //
console.log( window.a ); //
console.log( 'a' in window ); //true let user = 'ghostwu';
console.log( user ); //ghostwu
console.log( window.user ); //undefined
console.log( 'b' in window ); //false /*
var RegExp = 'ghostwu';
console.log( RegExp ); //ghostwu
console.log( window.RegExp ); //ghostwu
console.log( 'RegExp' in window ); //true
*/ let RegExp = 'ghostwu';
console.log( RegExp ); //ghostwu
console.log( window.RegExp ); //function RegExp() { [native code] }
console.log( 'RegExp' in window ); //true

const关键字是用来定义常量的,它有如下特性:

.块级作用域

.声明的时候,必须赋予初始值

.不能被重新赋值

.如果值是一个对象, 那么对象里面的属性是允许被修改的

.不能跟其他标识符重名

         const user = 'ghostwu';
console.log( user );
user = 'zhangsan'; //报错, 不能重新赋值
 const user; //报错,定义的时候 没有给初始值
         const user = {
name : 'ghostwu'
};
console.log( user.name ); //ghostwu
user.name = 'zhangsan'; //对象的属性允许被修改
console.log( user.name ); //zhangsan
        const user = {
name : 'ghostwu'
};
user = { //报错,不能重新给user赋值
name : 'zhangsan'
}
console.log( user.name ); //报错
         var a = 10;
const a = 10; // 报错,重定义错误
         let a = 10;
const a = 10; //报错,重定义错误
        if ( true ) {
const a = 10;
console.log( a ); //
}
console.log( a ); //报错:a is not defined

[js高手之路] es6系列教程 - var, let, const详解的更多相关文章

  1. [js高手之路] es6系列教程 - 对象功能扩展详解

    第一:字面量对象的方法,支持缩写形式 //es6之前,这么写 var User = { name : 'ghostwu', showName : function(){ return this.nam ...

  2. [js高手之路] es6系列教程 - 迭代器与生成器详解

    什么是迭代器? 迭代器是一种特殊对象,这种对象具有以下特点: 1,所有对象都有一个next方法 2,每次调用next方法,都会返回一个对象,该对象包含两个属性,一个是value, 表示下一个将要返回的 ...

  3. [js高手之路] es6系列教程 - promise常见用法详解(resolve,reject,catch,then,all,race)

    关于promise我在之前的文章已经应用过好几次,如[js高手之路]Node.js+jade+express+mongodb+mongoose+promise实现todolist,本文就来讲解下pro ...

  4. [js高手之路] es6系列教程 - 迭代器,生成器,for...of,entries,values,keys等详解

    接着上文[js高手之路] es6系列教程 - 迭代器与生成器详解继续. 在es6中引入了一个新的循环结构for ....of, 主要是用来循环可迭代的对象,那么什么是可迭代的对象呢? 可迭代的对象一般 ...

  5. [js高手之路] es6系列教程 - 函数的默认参数详解

    在ES6之前,我们一般用短路表达式处理默认参数 function show( a, b ){ var a = a || 10; var b = b || 20; console.log( a, b ) ...

  6. [js高手之路] es6系列教程 - 箭头函数详解

    箭头函数是es6新增的非常有意思的特性,初次写起来,可能会觉得别扭,习惯之后,会发现很精简. 什么是箭头函数? 箭头函数是一种使用箭头( => )定义函数的新语法, 主要有以下特性: 不能通过n ...

  7. [js高手之路] es6系列教程 - 不定参数与展开运算符(...)

    三个点(...)在es6中,有两个含义: 用在形参中, 表示传递给他的参数集合, 类似于arguments, 叫不定参数. 语法格式:  在形参面前加三个点( ... ) 用在数组前面,可以把数组的值 ...

  8. [js高手之路]es6系列教程 - 解构详解

    解构通俗点说,就是通过一种特定格式,快捷的读取对象/数组中的数据的方法, es6之前,我们通过对象名称[键] 读取数据 var User = { 'name' : 'ghostwu', 'age' : ...

  9. [js高手之路] es6系列教程 - Set详解与抽奖程序应用实战

    我们还是从一些现有的需求和问题出发,为什么会有set,他的存在是为了解决什么问题? 我们看一个这样的例子,为一个对象添加键值对 var obj = Object.create( null ); obj ...

随机推荐

  1. C++ 获取文件夹下的所有文件名

    获取文件夹下所有的文件名是常用的功能,今天再一次有这样的需求,所有就在网上查找了很多,并记下以供后用. 原文:http://blog.csdn.NET/cxf7394373/article/detai ...

  2. 【Android Developers Training】 56. 更效率地加载大图片

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  3. 把本地git仓库中的项目引入到码云上

    一.安装git软件和TortoiseGit客户端(git需配置环境变量,但安装时已经配置好,无需考虑) 二.生成公钥和私钥(建立与码云的连接) 三.在码云上新建项目(建议在组织的基础上)   四.在码 ...

  4. redis内存管理

    Redis主要通过控制内存上线和回收策略来实现内存管理. 1. 设置内存上限 redis使用maxmemory参数限制最大可用内存.限制的目的主要有: 用户缓存场景,当超出内存上限maxmemory时 ...

  5. (转载)Oracle10g 数据泵导出命令 expdp 使用总结(三)

    原文链接:http://hi.baidu.com/edeed/item/19aa0df856da3e19a6298894 Oracle10g 数据泵导出命令 expdp 使用总结(一) 14. JOB ...

  6. 总结下Redux

    Redux 和 React 没有直接关系,它瞄准的目标是应用状态管理. 核心概念是 Map/Reduce 中的 Reduce.且 Reducer 的执行是同步,产生的 State 是 Immutabl ...

  7. jsp获取当前日期,包括星期几

    <%@ page language="java" pageEncoding="GB2312" %> <html> <head> ...

  8. 如何通过css设置表格居中

    CSS控制整个表格居中,不只是让表格里的文字居中,是整个表格居中1. 不用table的Align="center",要用CSS实现2. 不加<center></c ...

  9. 面向对象设计模式——观察者(OBSERVER)模式

    定义 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新.  Observer模式描述了如何建立这种关系.这一模式中的关键对象是目标(subject ...

  10. Luogu 1060 开心的金明 / NOIP 2006 (动态规划)

    Luogu 1060 开心的金明 / NOIP 2006 (动态规划) Description 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间.更让他高兴的是,妈妈昨 ...