JavaScript高阶——ES6学习笔记
1. let、const、作用域
ES5及以前的JavaScript不支持块级作用域 并且声明变量使用的是var。
在ES6当中,新增了const和let两个关键词来控制作用域。
let
- let的使用方法类似于var,但是只在声明的变量只在作用域内生效。
{
var a = 100;
let b = 200;
console.log(a);
}
console.log(b);//输出100 b is not defined
{
var a = 100;
let b = 200;
console.log(a);
console.log(b);
}//输出为100 200
- let命令更适合用于for循环语句
{
var a=[];
for(var i=0;i<10;i++){
a[i]=function(){
console.log(i);
};
}
a[6]();
}//输出为10
{
var a=[];
for(let i=0;i<10;i++){
a[i]=function(){
console.log(i);
};
}
a[6]();
}//输出为6
在同样的函数体下,运用不同的关键字,得到的结果不一样。
因为var是全局变量,所以循环结束后值会被覆盖掉。而let有自己的作用域块,所以在for循环表达式中使用let等价于在代码块中使用let,在每次执行循环体之前,JS 引擎会把 i 在循环体的上下文中重新声明及初始化一次。(来源于知乎:for循环的理解及在for循环中使用let和var)
使用let声明变量时,for循环在设置循环变量的部分是一个父作用域,循环体内部又是一个独立的子作用域。
- 变量提升
含义:函数及变量的声明都将被提升到函数的最顶部。
var声明的变量无论其实际声明位置在何处,都会被视为声明于所在函数(或全局)的顶部,这就是变量提升。let不会进行变量提升。
console.log(a);
var a = '你好我是a';
//输出为undefined
该代码实际上就等于
var a;
console.log(a);
a = '你好我是a';//undefined '你好我是a'
这就是变量提升。
- 暂时性死区
ES6明确规定,如果区块中存在let和const命令,则这个区块对这些命令声明的变量从一开始就形成封闭作用域。
在代码块内,使用let命令声明变量之前,该变量都是不可用的,这个区域被称为“暂时性死区”(TDZ)。
var tem = 123;
if(true){
tem = 'abc';
var tem;
console.log(tem);//输出为abc
//使用let时
var tem = 123;
if(true){
tem = 'abc';
let tem;
console.log(tem);
}//输出为 ReferenceError: Cannot access 'tem' before initialization
- let不允许重复声明
作用域
定义:变量或函数在起作用的区域。
JavaScript采用的是“词法作用域”,即在变量作用域取决于变量所在的代码区域。
ES6中新增了“块作用域”,也包含了ES5中的“全局作用域”和“函数作用域”。
分类:全局作用域、函数作用域、块作用域。
作用域链
每一段JavaScript代码(全局代码或函数)都有一个与之关联的作用域链(scope chain)。
当JavaScript查找变量x的时候( 变量解析),会从当前作用域开始跟随作用域链向上查找,直到找到x变量的声明,若到达全局作用域中仍未找到,则抛出一个引用错误(ReferenceError)异常。
当只有全局作用域和函数作用域时会发生的问题:
- 内层变量可能会覆盖外层变量;
- 用来计数的循环变量泄露为全局变量。
因此块作用域解决了这系列的问题。
let形成块作用域
- ES6允许块级作用域任意嵌套,一对{ }即为一个块级作用域。
- 内层作用域可以定义与外层作用域同名变量。
- 块级作用域的出现使得ES5中惯用的IIFE(立即执行匿名函数)不再必要了。
const命令
与let不同点:声明一个只读的常量,一旦声明,其值不能改变且必须立即初始化。
当常量保存的不是一个值,而是一个地址的时候,该常量所引用的对象是可以更改成员的,只是不能更改该常量保存的地址。
const foo={y:10};
foo.x=100;
console.log(foo.x);
//输出为100
// foo={n:1000};
当取消注释foo={n:1000};时,就会报出TypeError: Assignment to constant variable.
顶层对象
浏览器的顶层对象为window,Node的为global。
var定义的变量会关联到顶层对象中,let和const不会。