let关键字
作用域绑定在最近的{…}块中
let
在使用时会绑定离它最近的{…}作为作用域。原本在ES6以前是没有块级作用域的概念,在ES6引入了let、const
关键字之后就有了块级作用域。实际上这个块级作用域并不是我们平常理解的块级作用域,仅当变量是由let、const
关键字声明时,这些关键字声明的变量其作用域会绑定在这个块上,若是使用var
关键字声明,其变量依然会成为全局变量。
使用这个特性我们可以很好的解决 for 循环全局变量污染的问题
if(true){
{
let a = 10;
var b = 20;
console.log(a); // 10
}
console.log(a); // ReferenceError
}
console.log(b); // 20
无变量提升
let
关键字在使用的时候,不像var
那样存在变量提升的情况。它必须先声明再使用。
function fn(){
console.log(a); // undefined
console.log(b); //ReferenceError
var a = 10;
let b = 20;
}
fn();
//上述代码等价于
function fn(){
var a; //var变量提升至所在作用域顶部
console.log(a); // undefined
console.log(b); //ReferenceError
a = 10;
let b = 20;
}
fn();
暂时性死区
所谓暂时性死区就是,你在块级作用域使用let
声明了一个变量i
,同时你在外部作用域也声明的一个同名变量i
。若你在let
声明这个变量前使用它,它并不会像以前的那样去上级作用域寻找这个变量,仅会在该作用域内寻找变量,又因为变量使用let
声明,并且声明在其使用之后,就会抛出ReferenceError。因为使用let
在作用域内声明了同名变量,它会屏蔽外界变量,这个块级区域就被称为暂时性死区。
var a = 20;
//if{}内形成暂时性死区
if(true){
console.log(a); // ReferenceError
let a = 10;
}
-------------
var b = 20;
//不是同名变量,没有暂时性死区
if(true){
console.log(b); // 20
let a = 10;
}
const
声明时必须赋值
const
关键字的特性和let
相同,let
有的特性const
都具有。不同点是它在声明的同时必须赋予一个值,否则抛出SyntaxError。
const a; // SyntaxError
赋值后不可改变
这里const
关键字声明的变量能否更改还需要看具体的情况。
若const
声明的是一个基本数据类型,则不能更改其值
const a = 10;
a = 20; // TypeError
但是如果const
声明的是一个复杂数据类型,则可以更改复杂数据类型变量内部的值,不可更改该复杂数据类型变量本身
const b = [1,2,3];
b[1] = 100;
console.log(b); // [1,100,3]
b = [3,4,5]; //TypeError
箭头函数
最初使用箭头函数的目的就是为了简化函数声明的操作,但它的作用不仅如此。我们都知道this
指针的指向在不同地方其指向不同,例如在构造函数中其指向就是它的实例化对象,在class
中的constructor
中也是同样的指向自身的实例化对象,而在普通函数中其指向的是函数的调用者。
箭头函数中的this
是根据上下文环境确定的
箭头函数this
指向的是被声明的作用域里面
let btn = document.querSelector('.btn');
btn.onclick = function(){
setTimeout(function(){
console.log(this); // window
},1000);
}
------------
//在定时器的回调函数中使用箭头函数则其this会根据上下文指向btn对象,而不是指向window
btn.onclick = function(){
setTimeout(()=>{
console.log(this); // btn
},1000);
}
多种简写形式
当形参只有一个且函数体内仅有一句返回值时
let sum = n => n*3;
//等价一
let sum = (n) => {
return n*3;
}
//等价二
let sum = function(n){
return n*3;
}
函数体中只有一句代码,且代码的执行结果就是返回值,可以省略大括号
let sum = (a,b) => a+b;
//等价一
let sum = (a,b) => {
return a + b;
}
//等价二
let sum = function(a,b){
return a + b;
}
解构
数组的解构
在es6中我们可以使用新的方式来命名多个变量,这种新的声明赋值方式就叫解构
//传统命名多个变量并赋值的方式
let a = 10,b = 20,c = 30;
//采用数组解构的方式
let arr = [10,20,30];
let [a,b,c] = arr; //a = 10,b = 20,c = 30
//当变量数量大于数组长度
let arr = [1,2,3];
let [a,b,c,d] = arr; //a = 1,b = 2, c = 3,d = undefined //多余的变量为未定义
//当变量数量少于数组长度
let arr = [1,2,3];
let [a,b] = arr; //a = 1,b = 2 //多余的直接被截断
--------------
//对象解构
let obj = {
name:'Asuhe',
age: 18,
sex: '男'
}
let {name:myname,age:myage,sex:mysex} = obj; //myname = 'Asuhe',myage = 18,mysex = '男' //按匹配相同名称,即使乱序也会匹配上
//等价于
let myname = 'Asuhe';
let myage = 18;
let sex = '男';
----------------
let {name,age,sex} = obj;
等价于
let name = 'Asuhe';
let age = 18;
let sex = '男';
剩余参数
在es6中新扩展了一种方法可以使函数的形参接收不定数量的实参,那就是使用剩余参数。我们知道在以前js同样支持函数形参和实参数量不匹配,即使定义函数时形参列表为空我们依然可以使用arguments
对象获取到实参。但在es6新增的箭头函数中并不支持arguments
,所以es6扩展了...args
剩余参数来解决这个问题。
//传统获取所有形参
function foo(){
console.log(arguments[0]); //1
console.log(arguments[1]); //2
console.log(arguments[2]); //3
}
foo(1,2,3);
//使用剩余参数
function foo(a,...args){ //剩余参数必须放在最后一个形参的位置
console.log(a); //1
console.log(args); //[2,3,4,5] //以数组的形式存储值
}
foo(1,2,3,4,5);