注意,写在开头

function test(x = 1) {var x  // 不报错console.log(x)
}
function test1(x = 1) {let x = 10 // 报错console.log(x)
}

let的变量名不可以和参数中的名称相同。而var并不限制,说白了就是希望你规范使用变量名。
形参原则上数组函数内部的临时变量,但是形参其实在内存中有独立的空间存储。

阮一峰ES6 - let

思考,在编写代码时,有es5、es6的语法,究竟是否有块级作用域?
ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。

1. var关键字可以重复声明

var num1 = 1;
var num1 = 100;
console.log(num1) // 100

2. let块级作用域

2.1 同一作用域下不能重复声明(无论是let/var/const声明)

let num1 = 1;
var num1 = 100; // 报错 重复定义
var a = 10;
let a = 10; // 报错
function test(a){let a = 10; // 预编译时,形参a已定义,重复声明报错
}
let a = 1;
function a() { } // 报错
let a = 1;
{function a() { } // 不报错
}
// 函数提升是在当前(块级)作用域下提升
// 转译后
"use strict";var a = 1;
{var _a = function _a() {}; // 不报错}
function test(a) {{let a = 10;}console.log(a) // undefined
}
test()

2.2 let不会提升,会产生一个暂时性死区,在变量声明前访问会报错

var a = a;
console.log(a) // undefined
let x = x; // 报错
// 在变量x的声明语句还没有执行完成前,就去取x的值,导致报错”x 未定义“。
// 这里不要把赋值语句拆分为声明和赋值2步理解
  • 以下3种情况
var x = 1;
{// 此处=右的x取的是块级作用域内的// 暂时性死区let x = x;console.log(x) // 报错// Uncaught ReferenceError: Cannot access 'x' before initialization
}

// 转译ES5
"use strict";var x = 1;
{var _x = _x;console.log(_x); // undefined
}

这里注意: 因为es5不存在暂时死区。let x = x 的问题在于,右侧x是取值并赋值的操作,而这个时候在es6里,x并没有完成初始化,所以取值x的时候就会失败。
而var是不存在这种问题的。因为es6严格规定了初始化流程就是变量声明必须初始化且不允许取值。也就是说声明语句不可以有对该变量的引用。

转译并不能百分百还原。对应let转var这里就出现了以上的情况。
有些浏览器不支持块级作用域(大括号)。
转译结果和babel的版本也有关系,有可能转译后去除了大括号或转成IIFE或其他形式。

var x = 1;
{let x;x = x;console.log(x) // undefined
}

"use strict";var x = 1;
{var _x;_x = _x;console.log(_x); // undefined
}
// 这个本身就是ES5不需要转
var x = 1;
{x = x;console.log(x) // 1
}
let a ;
a = a
console.log(a) // undefined
if (true) {// TDZ开始tmp = 'abc'; // ReferenceErrorconsole.log(tmp); // ReferenceErrorlet tmp; // TDZ结束console.log(tmp); // undefinedtmp = 123;console.log(tmp); // 123
}
function bar(x = y, y = 2) {return [x, y];
}bar(); // 报错
// 参数x默认值等于另一个参数y,而此时y还没有声明,属于“死区”。如果y的默认值是x,就不会报错,因为此时x已经声明了。

2.3 typeof不再是一个百分之百安全的操作

typeof x; // ReferenceError
let x;

注意

for (var i = 0; i < 10; i++) {arr[i] = function () {console.log(i)}
}
for (var i = 0; i < 10; i++) {arr[i]() // 打印0-9
}
// 第二个for循环里,var i重新赋值了,恰好是i

var arr = [];
for (var i = 0; i < 10; i++) {arr[i] = function () {console.log(i)}
}
// 上个for循环var i是全局的,退出循环后为10
for (var index = 0; index < 10; index++) {arr[index]() // 10个10
}

==================================================

let是在块中声明的变量,每当声明一个function都会传入当前for的块中单独的i进去。也就是说let是块变量,在自己的块,或者子块中使用。而不是只在函数或全局作用域中使用。立即执行函数是为了将每次的i作为函数作用域中的局部变量传入与外界的i隔离。

// 用let声明,由于存在父子级作用域,相当于也形成了闭包
var arr = [];
for (let i = 0; i < 10; i++) {arr[i] = function () {console.log(i)}
}
// 即使index用let打印的也是0-9
for (var index = 0; index < 10; index++) {arr[index]() // 0-9
}
// 转译之后
"use strict";var arr = [];var _loop = function _loop(i) {arr[i] = function () {console.log(i);};
};for (var i = 0; i < 10; i++) {_loop(i); // 这里立即执行了
}for (var index = 0; index < 10; index++) {arr[index](); // 0-9
}

2.4 for循环作用域

  • for循环的特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域
for (var i = 0; i < 10; i++) {let i = 'a' console.log(i) // 10个a // 循环的index i是声明在全局的
}
console.log(i) // 10
for (let i = 0; i < 10; i++) {// for循环内的块级作用域// for花括号内的块级作用域并不相同let i = 'a'console.log(i) // 10个a
}
for (let i = 0; i < 10; i++) {var i = 'a' // 报错 // 因为for循环内,这里var声明的i会提升到全局// 而for循环条件又用let声明一次i,重复声明了console.log(i)
}
if (1) {let a = 1;console.log(a) // 1{let a = 10;console.log(a) // 10}
}

以前遇到的有IIFE里不用关键字声明的吗

let a = 1;
(function(){a = 10; console.log(a) // 10
})()
console.log(a) // 10
let a = 1;
(function(){let a = 10;console.log(a) // 10
})()
console.log(a) // 1
var a;
(function () {a = 10;console.log(a) // 10
})();
(function () {a = 100;console.log(a) // 100
})();
console.log(a) // 100
(function () {var a = 10;console.log(a) // 10
})();
(function () {var a = 100;console.log(a) // 100
})();
console.log(a) // 报错
// Uncaught ReferenceError: a is not defined

思考:在index.html文件的script标签里编码,既有es5的语法,又有es6的语法,在浏览器中打开时,浏览器会将所有代码转译成es6吗
不会转译,浏览器不同的版本对es的支持不一样。(现代浏览器基本都支持ES6)
现在普遍兼容es6的语法。但对特殊的语法需要babel转译, 包括对象的拓展,类的修饰等等,这些是需要babel转译的。

块级作用域等于匿名函数的立即调用吗?并不,块级作用域没有返回值。二者本质不同。

思考总结,在块级作用域{}内,用let/const声明的和父作用域同名的变量x,在转译ES6的时候,会被编译成另一变量_x

ES6-2 块级作用域与嵌套、let、暂行性死区相关推荐

  1. ES6中块级作用域下的函数声明

    背景 因为ES5的时候没有块级作用域,所以ES5规定不能再if这样的块中声明函数,但是为了兼容各大浏览器并没有严格遵守这条规定. ES6的时候引入了块级作用域,规定在块级作用域中声明函数就相当于使用l ...

  2. [ES6] 细化ES6之 -- 块级作用域

    所谓的块级作用域,可能是一个{},一个代码块,一句话 let关键字 let 与 var 区别 区别 var let 变量提升 有 无 作用域 全局作用域.函数作用域 全局作用域.函数作用域和块级作用域 ...

  3. ES6 块级作用域详解

    什么是块级作用域 ES6 中新增了块级作用域.块作用域由 { } 包括,if 语句和 for 语句里面的 { } 也属于块作用域. 为什么需要块级作用域 第一种场景:内部变量会覆盖外部变量 var t ...

  4. 搭建Babel运行环境,Traceur ES6模板,块级作用域,let和const命令

    搭建Babel运行环境 Babel(http://babeljs.io/)可用于将使用ES6语法的脚本转化为ES5语法的脚本,基本功能的安装步骤如下: 1.安装node解释器和npm包管理工具 2.安 ...

  5. es6 ie不兼容 函数_ES6:什么是块级作用域?

    在 ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景. 我们先来看一下下面这种情况:内层变量可能会覆盖外层变量. var txt = '外层变量-->你好呀';func ...

  6. java区块作用域_ES6-let、const和块级作用域

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

  7. javascript中作用域、全局作用域、局部作用域、隐式全局变量、块级作用域、作用域链、预解析

    作用域 作用域指的是代码的作用范围,按照作用域划分变量可分为全局变量和局部变量:作用域可分为: 全局作用域: 指全局变量作用的范围:全局变量指的是通过var在函数外面声明的变量,在js中任何位置都可以 ...

  8. 块级作用域和函数作用域

    函数作用域与块级作用域 函数作用域:在函数内部声明的变量只能影响到变量所在函数体本身,无法从外部对函数内部的变量进行调用,被称为'函数作用域' 块级作用域:ES6 引入了 let 和 const 关键 ...

  9. let、const和var的区别(涉及块级作用域)

    let .const和var的区别 let.const.var在js中都是用于声明变量的,在没有进行ES6的学习前,我基本只会使用到var关键字进行变量的声明,但在了解了ES6之后就涉及到了块级作用域 ...

最新文章

  1. Java垃圾回收之新生代垃圾收集器
  2. 论手残党画交互原型的正确姿势
  3. (转)Fiddler教程(Web调试工具)
  4. python/numpy将矩阵保存为文本文件
  5. Linux运行可执行文件
  6. wince6.0中文内核定制
  7. python用map提取一个数的个十百位数_如何使用python中的map函数?
  8. 卡尔曼滤波,最最容易理解的讲解.找遍网上就这篇看懂了(转载)
  9. 微课|玩转Python轻松过二级(2.1.4节):列表、元组、字典、集合概述
  10. git学习 add - commit - init
  11. 安卓模拟器调试GPS
  12. 远程访问型木马——灰鸽子软件的使用(含免杀)
  13. 阿里巴巴国际站关键字抓取工具
  14. GAN生成图像质量的两个评价指标——IS与FID
  15. 银河麒麟系统PDF转Word
  16. 解决mysql每天12点的dos弹框
  17. 西游记采访实录(玉帝访谈录)
  18. Excel数据分析入门-数据图表
  19. python中quad_python scipy integrate.quad用法及代码示例
  20. ASCII,ISO8859-1,GBK,GB18030,Unicode,UTF-8详解

热门文章

  1. java 堆内存分析_JVM内存堆布局图解分析
  2. python教学视频a_2019何老师一个月带你玩转Python分布式爬虫实战教程视频(视频+源码)...
  3. 删除 索引 外键 mysql_MySQL无法删除外键约束中所需的索引
  4. linux交叉编译tile环境搭建,g ++ - 在Ubuntu中在32位上交叉编译64位程序时,缺少包含“bits / c ++ config.h”...
  5. Caffe2 Compilation Error gflags.cc' is being linked both statically and dynamically into this execut
  6. ASP.NET Core Web 应用程序系列(四)- ASP.NET Core 异步编程之async await
  7. LDAP第三天 MySQL+LDAP 安装
  8. 启用系统登录失败处理功能
  9. 2015 UESTC 数据结构专题G题 秋实大哥去打工 单调栈
  10. [转]Android开发,实现可多选的图片ListView,便于批量操作