1.介绍

  总的来说,ES6是在ES2015的基础上改变了一些书写方式,开放了更多API,这样做的目的最终还是为了贴合实际开发的需要。如果说一门编程语言的诞生是天才的构思和实现,那它的发展无疑就是不断填坑的历史。ES6正是为了填一些坑。

  我对ES6语法的学习,主要在浏览器端,参考阮一峰大神的ES6入门教程,添加了一些个人理解的注释和遇到的小问题,欢迎批评指正,共同进步。

   浏览器端引用的依赖文件和本文案例  可在https://github.com/chanceLe/ES6-Basic-Syntax 找到。

2.基础部分

2.1let和const关键字

let命令声明变量,类似var,但所声明的变量只在let代码块有效。  

           {
let a = 1;
var b = 2;
}
console.log(b);
console.log(a); //报错,找不到。
//for循环的计数器,就很适合用let
for(let i=0;i<5;i++){
console.log(i);
}
//上面的代码的计数器i,只在for循环体内有效。

   {}在ES6中用来形成块级作用域,后边会说到。  

      var a = [];
for(var i=0;i<10;i++){
a[i] = function(){
console.log(i);
}
}
        
      a[6]();  //10  到九循环完,又加了1,换成let会得到期望结果。

  var声明的变量全局范围内都有效。所以每次循环,新的i值都会覆盖旧值
  let声明的仅在块级作用域内有效,最后输出6

   let不会发生变量提升的现象,所以一定要在定义后使用,否则报错。

  暂时性死区:只要块级作用域内存在let命令,它所声明的变量就绑定这个区域,不再受外部影响。

       var tmp = 123;
if(true){
tmp = "abc";
console.log(tmp,"11"); //"abc"
let tmp;
}
console.log(tmp,"22"); //"123"

  书上说,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭
  作用域,凡是声明之前使用的,都会报错。

  实际情况,let不会报错,const会报错(这可能跟浏览器端转码有关,版本为5)。

  有些死区比较隐蔽,不太容易发现:

       function bar(x=y,y=2){
return [x,y];
}
console.log(bar()); //书上说这里由于y没有定义,应该报错,实际是 [undefined,2] function bar2(x=2,y=x){
return [x,y];
}
console.log(bar2()); //[2,2]正常

  不允许重复声明,let不允许在相同作用域内,重复声明同一个变量:

          function fun(){
let a = 10;
// var a = 5; //报错。
// let a = 1; //报错
}

  不能在函数内部重新声明参数:

      function fun1(arg){
      // let arg; //报错
{
let arg; //不报错
}
}

  const命令
   声明一个只读的常量。一旦声明,常量的值就不能改变。
   同时也说明,一旦声明,就要立即初始化,否则也报错。

       const PI = 3.1415;
console.log(PI);
// PI = 3; //报错 只读的
// const circle; //报错,一旦声明,必须立即初始化。
/*
* const的作用域与let命令相同:只在声明所在的块级作用域有效。
*/
if(true){
const m = 5;
}
// console.log(m); //未定义

  与let相似:
   const命令声明的常量也不提升,同样存在暂时性死区,只能在声明的位置后使用。
   也不可以重复声明。

  对于复合类型的变量,变量名不指向数据,而是指向数据所在的地址。const命令只
   是保证变量名指向的地址不变,并不保证该地址的数据不变,所以将一个对象声明为常量,
   必须非常小心。

       const foo = {};
foo.prop = 123;
console.log(foo.prop);
//上面的常量foo存储的是对象的地址,这个地址不可变,但依然可以添加属性。
const a = [];
a.push("hello");
a.length = 0;
// a = ["Dave"] //报错,赋值就是更换地址,不行的。
//如果真的想把对象冻结,应该使用Object.freeze方法。
const foo2 = Object.freeze({});
//常规模式下,下面一行不起作用
//严格模式下,会报错
foo.prop = 123;

  ES5只有两种声明变量的方法:var和function。  
  ES6有6种:var function let const class import

  全局对象属性:
   全局对象是最顶层的对象,在浏览器环境下指的是window对象,在node指的是
   global对象。ES5中,全局对象的属性和全局变量是等价的。
   未声明的全局变量,自动成为全局对象window的属性,这被认为是js的最大败笔。
   ES6为了改变这一点,一方面规定,为了保持兼容性,var命令和function命令声明的全局变量,
   依旧是全局对象的属性,另一方面规定,let,const,class命令声明的全局变量不属于全局对象的
   属性。也就是说,从ES6开始,全局变量将逐渐与全局对象的属性脱钩。

  2.2块级作用域:

  ES5只有全局作用域和函数作用域,没有块级作用域,有很多不合理场景:
  1.内层变量可能会覆盖外层变量。

       var tmp = new Date();
function f(){
console.log(tmp);
if(false){
var tmp = "hello world!";
}
}
f(); //undefined 声明提升,后边的定义把前边的覆盖掉了。

  2.用来计数的循环变量泄漏为全局变量。典型的var定义的循环,上边有代码体现。

  let实际上为js新增了块级作用域。下面的代码两个代码块都声明了n,运行输出5,表示外层代码不受内层代码块的影响。如果是var定义,就会收到影响,输出10;

       function f1(){
let n = 5;
if(true){
let n = 10;
}
console.log(n);
}
f1();
      //es6允许块级作用域的任意嵌套:
{{{{{ let insane = "hello world" }}}}}
//上面代码使用了五层块级作用域,外部不能访问内部的变量。
//块级作用域实际上使得广泛应用的立即执行匿名函数(IIFE)不再需要了。
//IIFE写法
(function(){ })()
//块级作用域写法
{ }
/*
       * 块级作用域与函数声明:
* ES5规定,函数只能在顶层作用域和函数作用域之中声明,不能在块作用域中声明,
* 情况一:
* if(true){
* function(){}
* }
* 情况二:
* try{
* function(){}
* }

  这两种情况,根据ES5的规定都是非法的。但是浏览器没有遵守这个规定,可以运行,在严格
  模式下,还是会报错。

  ES6引入了块级作用域,明确允许在块级作用域中声明函数。
   块级作用域中,函数声明语句的行为类似于let,在块级作用域之外,不可以引用。
   因为块级作用域对作用域之外没有影响,这个差异会对老代码产生很大影响,为了减轻这个不兼容
   问题,ES6在附录B中规定,浏览器可以不遵守上面的规定,有自己的行为方式。

  1.允许在块级作用域内声明函数。
   2.函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
   3.同时,函数声明还会提升到所在块级作用域的头部。
   上面的3个规则只对ES6 的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域当做let处理。

  考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式。
   ES6的块级作用域允许声明函数的规则,只在使用大括号的情况下成立,没有使用大括号,会报错。

ES6-let、const和块级作用域的更多相关文章

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

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

  2. ES6入门一:块级作用域(let&const)、spread展开、rest收集

    let声明 const声明 块级作用域 spread/rest 一.let声明与块作用域 在ES6之前,JavaScript中的作用域基本单元就是function.现在有了let就可以创建任意块的声明 ...

  3. let/const及块级作用域

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

  4. ES6学习笔记之块级作用域

    ES6学习笔记:块级作用域 作用域分类 全局作用域 局部作用域 块级作用域 全局作用域示例 var i=2; for (var i = 0; i < 10; i++) { } console.l ...

  5. ES6的 let const 以及块级作用域

    let声明变量 用法类似于var,但是所声明的变量只在let所在的代码块内有效. 1 . 在ES6环境下,let声明的变量不能在声明之前调用. 例: console.log(i); //会报错,这叫做 ...

  6. 开始学习es6(二) let 与 const 及 块级作用域

    1.var JavaScript中,我们通常说的作用域是函数作用域,使用var声明的变量,无论是在代码的哪个地方声明的,都会提升到当前作用域的最顶部,这种行为叫做变量提升(Hoisting) cons ...

  7. ES6——块级作用域

    前面的话 过去,javascript缺乏块级作用域,var声明时的声明提升.属性变量等行为让人困惑.ES6的新语法可以帮助我们更好地控制作用域.本文将详细介绍ES6新引入的块级作用域绑定机制.let和 ...

  8. 《浏览器工作原理与实践》<09>块级作用域:var缺陷以及为什么要引入let和const?

    在前面我们已经讲解了 JavaScript 中变量提升的相关内容,正是由于 JavaScript 存在变量提升这种特性,从而导致了很多与直觉不符的代码,这也是 JavaScript 的一个重要设计缺陷 ...

  9. ECMAScript6 入门教程 初学记录let命令 块级作用域

    一.基本语法-let命令 (1)ES6新增了let命令,用来声明变量.所声明的变量,只在let命令所在的代码块内有效. 循环的计数器,就很合适使用let命令.计数器i只在for循环体内有效,在循环体外 ...

随机推荐

  1. python技巧31[python中使用enum][转]

    以下几种方法来模拟enum:(感觉方法一简单实用) # way1 class Directions:     up = 0     down = 1     left = 2     right =3 ...

  2. springmvc 孔浩 hibernate code

    model--User package model; import javax.persistence.Entity; import javax.persistence.GeneratedValue; ...

  3. This problem will occur when running in 64 bit mode with the 32 bit Oracle client components installed(在64位模式下运行安装了32位的Oracle客户端组件时,会发生此问题)

    部署win服务时出现下面的问题: 在事件查看器中看到如下错误: 日志名称: Application来源: ***调度服务日期: 2014/5/21 12:53:21事件 ID: 0任务类别: 无级别: ...

  4. EBS 11i升级R12

     http://blog.csdn.net/y657356105/article/details/8181081 概述 从EBS 11i升级至R12,总的来说更变较大的就是多OU访问(MOAC)和表视 ...

  5. 用NPOI操作EXCEL--巧妙使用Excel Chart

    在NPOI中,本身并不支持Chart等高级对象的创建,但通过l模板的方式可以巧妙地利用Excel强大的透视和图表功能,请看以下例子. 首先建立模板文件,定义两列以及指向此区域的名称“sales”: 创 ...

  6. 你好,Azure DevOps Server 2019;再见,Team Foundation Server

    微软正式发布Azure DevOps Server 2019的第一个版本,作为Team Foundation Server (TFS)2018的升级版本和替代产品. 这是目前市面上唯一一款将产品名称冠 ...

  7. Spring Boot 2 实践记录之 条件装配

    实验项目是想要使用多种数据库访问方式,比如 JPA 和 MyBatis. 项目的 Service 层业务逻辑相同,只是具体实现代码不同,自然是一组接口,两组实现类的架构比较合理. 不过这种模式却有一个 ...

  8. 一个基于ASP.NET(C#)的ACCESS数据库操作类

    using System; using System.Collections; using System.Collections.Specialized; using System.Data; usi ...

  9. 执行js-----Selenium快速入门(十四)

    Selenium能够执行js,这使得Selenium拥有更为强大的能力.既然能执行js,那么js能做的事,Selenium应该大部分也能做.这应该得益于JavascriptExecutor这个接口,而 ...

  10. 《ASP.NET MVC 5 破境之道》:第一境 ASP.Net MVC5项目初探 — 第一节:运行第一个MVC5项目

    第一境 ASP.Net MVC5项目初探 — 第一节:运行第一个MVC5项目 创建一个MVC项目,是很容易的,大部分工作,VS都帮我们完成了.只需要按照如下步骤按部就班就可以了. 打开VS2017,选 ...