1.let用法类似于var,但是let只在所在代码块有效
{ let a = 10; var b = 1; } a // ReferenceError: a is not defined. b // 1
2.let适用于for循环
for (let i = 0; i < 10; i++) { //... } console.log(i) //ReferenceError: i is not defined
3.let 与 var 的区别
//***** let***** var a = [] // 每一次循环,i都是新的变量,只在本轮循环有效 for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i) } } a[6](); // 6 //*****var***** var a = [] // 变量i是var声明的,全局有效,每一次循环,i都会发生变化,里面所有的i都指向同一个i for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i) } } a[6](); // 10
那么问题来了,使用let声明的i,在for循环条件中,每一次循环都是新的i,那么i如何记住上一次循环的值,来进行++,再到下一轮循环呢?答案是因为JavaScript引擎内部会记住上一轮循环的值,初始化本轮的变量i
时,就在上一轮循环的基础上进行计算。
4.for循环的父子作用域
for (let i = 0; i < 3; i++) { let i = 'abc'; console.log (i) } // abc // abc // abc
可以看出循环变量i与函数内部变量i不在同一作用域
5.“变量提升”概念
意思就是,一直以来var命令都会发生‘变量提升’的现象,意思就是变量可以在声明之前使用,输出的是“undefined”
6.let纠正了var的尴尬之处
// var 尴尬的地方,使用未声明的变量,竟然不报错 console.log(foo); //输出undefined var foo = 2; // let纠正了var 的这一现象,使用未声明的变量,报错 console.log(bar); //输出ReferenceError let bar = 2;
7.暂时性死区 (TDZ)
意思是,只要块级作用域{}存在let,用它来声明的变量,就不会受外部影响
var tmp = 123; if (true) { tmp = 'abc'; //ReferenceError let tmp;// TDZ结束 console.log(tmp) // undefined }
首先在{}中,存在let声明的tmp,那么tmp不受{}以外的变量影响,又因为在if里面的第一句使用到了tmp,这个东西又没有声明,看到总结的第5点就知道,它会报错。
所以,在let命令声明变量tmp之前,都属于变量tmp的死区!!
8.对死区使用 typeof 操作符
typeof x; // ReferenceError let x; // 然而,对一个不存在的变量使用typeof,却不报错 type of undeclared_var // "undefined"
所以,在没有let之前,typeof运算符是百分之百安全的,永远不会报错
9.let不允许重复再相同作用域内,重复声明同一个变量
// 报错 function func () { let a = 10; var a = 1; } // 报错 function func () { let a = 10; let a = 1; } // 报错 function func (arg) { let arg; } // 不报错 function func (arg) { { let arg; } }
10. 使用let代替立即执行匿名函数
// 一般立即执行匿名函数是这样的 var config = (function() { var config = [] config.push(1) config.push(2) config.push(3) return config }) // 使用let let config; { config = [] config.push(1) config.push(2) config.push(3) }
11.es6函数不被提升
一般使用‘use strict’开头,即严格模式,就是ES6
'use strict' function a () { console.log(1) } function f () { a() if (false) { function a () { console.log(2) } } }
f(); // 输出1
假如去掉严格模式语句,也就是老版本ES5状态下,是会输出2的,原因就是发生了函数的变量提升,即
function a () { console.log(1) } function f () { function a () { // function a() 被提升到最前面了,即使if语句不执行 console.log(2) } a() if (false) { function a () { console.log(2) } } } f(); // 输出2
12. const使用,物理内存地址不可更改
例如:
const a = { name = 'guang' }; a.name = 'lighter'; a.email = '123456789@qq.com' console.log(a); // 输出为: { name : 'lighter', email : '123456789@qq.com' }
上面代码不会报错,这是为什么呢?因为这个const为复合型变量,变量名不知想数据,而是指向数据所在的地址。const命令知识保证变量名指向的地址不变,而不保证该地址的数据不变,所以将一个对象生命为常量必须非常小心
const的使用可以参照:http://www.cnblogs.com/zczhangcui/p/6393304.html
对于const常量,例如:const a = 13,因为13这个物理位置是不可变的,所有不能更改a指向的地址。
假如想测定不让修改const 对象,不管它是否复合型变量,都不允许更改
Object.freeze(a); a.name = ' ' //报错 console.log(s)
------完------