什么是ES6
ECMAScript的简称,是于2015年6月正式发布的JavaScript语言的标准,正式名为ECMAScript 2015(ES2015),它的目标是使得JavaScript语言可以用来编写复杂的大型应用程序,成为企业级开发语言。
一些情况下ES6也泛指ES2015及之后的新增特性,即使之后的版本应该称为ES7、ES8等。
为什么使用ES6
每一次标准的诞生都意味着语言的完善,功能的加强,JavaScript语言本身也有一些让人不满意的地方。
- 变量提升特性增加了程序运行时的不可预测性
- 语法过于松散,实现相同的功能,不同的人可能会写出不同的代码
ES6新增的语法
let
ES6中新增的用于声明变量的关键字
使用let声明的变量没有作用域的提升。
console.log(num);
let num = 10;
Uncaught ReferenceError: Cannot access ‘num’ before initialization
at
这段代码就会报错,如果是var声明的就会显示num的值为undefined。
let声明的变量具有块级作用域
if (true) {
let a = 1;
}
console.log(let);
结果为 :Uncaught ReferenceError: let is not defined
at
在代码块内声明的变量不能在代码外边被访问到。
在循环中使用let
var arr = [1,2]
for (var i = 0; i < 2; i++) {
arr[i] = function () {
console.log(i);
}
}
i = 3;
arr[0]();//3
arr[1]();//3
先看使用var声明的i在最后执行时,打印的是3,这说明for循环中i这个变量其实是全局变量。在函数执行时,访问的i是全局变量的i。
如果换成了let
var arr = [1,2]
for (let i = 0; i < 2; i++) {
arr[i] = function () {
console.log(i);
}
}
i = 3;
arr[0]();//0
arr[1]();//1
即使是在外面改变了全局变量i的值,但是在for循环内部已经有了一个块级作用域的变量i了,每一次循环都会在当前的执行的代码块内声明一个变量i,函数就会打印当前作用域中的i。
使用let会出现暂时性死区
var num = 40;
if (true){
console.log(num);
let num = 10;
}
这段代码结果为:Uncaught ReferenceError: Cannot access ‘num’ before initialization
at
只要当前作用域存在使用let声明的变量,就无法访问上一级的同名的变量。如果声明在访问之后,就会出现报错。
总结
- let关键字就是用来声明变量的
- 使用let关键字声明的变量具有块级作用域
- 在一个大括号中,使用let关键字声明的变量才具有块级作用域 var 关键字是不具备这个特点的
- 防止循环变量变成全局变量
- 使用let关键字声明的变量没有变量提升
- 使用let关键字声明的变量具有暂时性死区特性
const
声明一个常量,常量就是值(内存地址)不能变化的量
具有块级作用域
if (true) {
const a = 10;
}
console.log(a);
结果是:Uncaught ReferenceError: a is not defined
at
在对常量声明的时候必须进行赋值
const PI ;
Uncaught SyntaxError: Missing initializer in const declaration
在声明常量时没有对常量进行初始化。
常量声明后不能进行修改
const PI = 3.1415926 ;
PI = 3.14;
Uncaught TypeError: Assignment to constant variable.
a
给常量进行了赋值操作。
但是如果是引用类型的数据
const arr = [1,2,3,4,56];
console.log(arr);
arr[0] = 2;
console.log(arr);
可以对常量保存的引用类型的数据进行内部的值的改变,常量检测的是它内部保存的内存地址不能出现修改。
总结
- const声明的变量是一个常量
- 常量不能重新进行赋值,如果是基本数据类型,不能更改值,如果是复杂数据类型,不能修改内存地址。
- 声明const时候必须要给定值。
let、const、var的区别
- var 声明定义的变量,有作用域的提升,没有块的概念,可以跨块访问,不能跨函数访问。
- let定义的变量,没有作用域的提升,只能在作用域里访问,不能跨块访问,也不能跨函数访问。
- const用来定义常量,使用时必须初始化(即必须赋值),且只能在块作用域里访问
解构赋值
ES6中允许从数组中提取值,按照对应位置,对变量赋值,对象也可以实现解构
数组解构
/数组解构允许我们按照对应的顺序从数组中提取相应的值,如果解构不成功返回undefined,如果等号右边的计算后的结果为unll或者undefined会抛出错误
let arr = [1,2,3]
let [a,b,c,d] = arr;
console.log(a);
console.log(b);
console.log(c);
console.log(d);
打印结果:
1
2
3
undefined
因为d没有在数组中找到相对应的值。
解构赋值
let arr = [1,2,3]
let [,,c] = arr;
console.log(c);//3
打印:
3
可以使用,占位将想要赋值的变量来对应相应的值。
重新赋值
let arr = [1,2,3]
let a = 10;
let b = 100;
[a,b] = arr;
console.log(a);//1
console.log(b);//2
通过这种方式可以给变量重新进行赋值。
默认赋值
let arr = [1,2,3]
let [a,b,c,d=100] = arr;
console.log(a);//1
console.log(b);//2
console.log(c);//3
console.log(d);//100
当变量找不到对象的值的时候就会被赋给等号后面的值
对象解构
解构赋值
let obj = {
name:'张三',
age:18,
phone:{
number:888
}
}
let {name,age} = obj;
console.log(name);//张三
console.log(age);18
变量名字与对象中的key去匹配,匹配成功后返回值
当变量名与对象中属性不一样时
let Mname = '李四';
let Mage = 28;
({name:Mname,
age:Mage} = obj);
console.log(Mname);//张三
console.log(Mage);//18
因为在解构时缺少了let关键字,所以需要加括号,使得左右两边形成完整的表达式。
对深层的复杂数据类型进解构
let {
phone :{
number:Mnum
}
} = obj;
console.log(Mnum);//888
这种赋值方式,还可以结合数组解构。
应用
// 1 变量值的交换
// let a = 10;
// let b = 20;
// [a,b] = [b,a];
// console.log(a);//20
// console.log(b);//10
// 2 函数返回多个值
// let [a,b,c] = (function () {
// return [2,2,4]
// })();
// console.log(a);//2
// console.log(b);//2
// console.log(c);//4
// let {name:Mname} = (function () {
// return {
// name:'张三'
// }
// })();
// console.log(Mname);//张三
// 3 作为参数列表
// function fn([a, b, c]) {
// console.log(a,b,c);
// }
// fn([1,2,3]);//1 2 3
// 扩展
// function fn2(a,{b,c,d}) {
// console.log(a,b,c,d);
// }
// fn2(1,{b:3,c:4,d:5})// 1 3 4 5
总结
- 解构赋值就是把数据解构分解,然后给变量进行赋值
- 如果解构不成功,变量跟数值个数不匹配的时候,变量的值为undefined
- 数组解构用中括号包裹,多个变量用逗号隔开,对象解构用大括号包裹,多个变量用逗号隔开
- 利用解构赋值能够让我们方便的去取对象中的属性跟方法
箭头函数
ES6中新增的定义函数的方式
// 箭头函数只能以函数表达式形式书写,
// ()=>{}, =>是必要的符号,不能省略,()参数,{}是方法体(函数体)
// 1.箭头函数参数
// 零个
var fn1 = () => {
console.log('箭头函数');
}
// 一个
var fn2 = num => {
return num;
}
// 如果返回内容是一个很简单的代码
// 需要返回的内容是一个很简单的代码。
var fn3 = num => num;
// console.log(fn3(3));
// 箭头函数中的this,不绑定this,箭头函数中的this将指向箭头函数定义的上下文
var fn4 = function () {
console.log(this);
}
var obj = {
name: '张三'
}
// 没有grguments在箭头函数中是未定义.
var fn5 = (name)=>{
console.log(arguments);
}
// fn5('张三')
扩展运算符 …
扩展运算符可以将一个数组形式的数据拆分,分割成数组中的序列,并且数据类型和原数组保持一致。
// 扩展运算符可以将一个数组形式的数据拆分,分割成数组中的序列,并且数据类型和原数组保持一致。
let arr = [1,2,3];
console.log(...arr);
console.log.apply(null,arr);
// 扩展合并数组
var arr1 = [1,2,3];
var arr2 = [3,4,5];
var arr3 = [...arr1,...arr2];
console.log(arr3);
// 将集合转换成数组
var NodeLi = document.querySelectorAll('div');
var HTMLColl = document.getElementsByClassName('box');
var arr4 = [...NodeLi];
var arr5 = [...HTMLColl];
console.log(NodeLi);
console.log(HTMLColl);
console.log(arr4);
console.log(arr5);
Array.from()可以将一个伪数组传换成数组
// Array.from()
// 将一个伪数组转换成数组
let obj = {
0: 'a',
1: 'b',
2: 'c',
3: 'd',
'length': 4
}
let arr = Array.from(obj);
let arr1 = Array.from(obj,item=>item+'Z','0')
console.log(arr);
console.log(arr1);
for (const k of obj) {
console.log(k);
}
模板字符串
使用模板字符串可以很轻松的将表达式插入到字符串当中,使用${}来作为分解。
es5中使用反斜杠来使字符串进行换行,而模板字符串本身就能直接识别换行。
Object.is()判断两个数据是否完全相等
Object.is()的作用基本与===一样,但是它在两个地方与后者有些不同
console.log(-0===+0);//true
console.log(Object.is(-0,+0));//false
console.log(NaN===0/0);//false
console.log(Object.is(NaN,0/0));//true
var num1 = 0/0 ;//NaN
var num2 = 1/0 ;//Infinity
var num3 = 1/0*0;//NaN