ES6
目录
ES6、babel、webpack和Less
目录
一、ES6中的let和const关键字
二、ES6中的解构
三、ES6中的字符串、数组的增强
四、ES6中的对象的增强
五、ES6中的Symbol类型
六、ES6中的Set和Map数据结构
七、ES6中的Promise对象
八、ES6中的类的定义
九、ES6中的箭头函数
十、Babel
10.1 工程化概述
10.2 Babel简介和安装
十一、ES6中的import from和export
十二、webpack
12.1 安装webpack和基本使用
12.2 webpack.config.js文件
12.3 和babel一起工作
十三、Less
13.1 基本使用
13.2 和webpack结合
ECMAScript 6于2015年6月正式发布,目标是使JavaScript可以用于编写复杂的大型应用程序,成为企业级开发语言,又称ES2015。
ECMAScript和JavaScript的关系?前者是后者的规格,后者是前者的实现。符合ECMAScript规则的还有Flash中的ActionScript和TypeScript。
可以在NodeJS中测试ES6,或者使用Webpack + Babel将ES6翻译为ES5。我们使用的nodejs版本是6.8.1,今天最新的已经有7了,但是6已经基本支持了绝大多数ES6语法。
ES6细枝末节很多(因为大家知道,JS是一个千疮百孔的语言,所以ES6在定稿的时候就特别细致,细枝末节极多),我们的课程注重实战中使用的、面试常考的ES6语言精粹。没有涉及到的知识点,我们会列出,有兴趣的同学可以自己学习。
一、ES6中的let和const关键字
ES5中只有var能够定义变量,作用域是在function中。
ES6中可以用let来定义变量,定义是块级作用域变量。
{ let a = 10; var b = 20; } console.log(a); //报错 console.log(b); //20
let的声明范围就是{}内部。
比如循环语句中定义函数,此时var:
var arr = []; for(let i = 0 ; i < 10 ; i++){ arr[i] = function(){ console.log(i); } } arr[6](); //10 输出10而不是6,因为函数中的i是全局作用域的i,定义其他函数的时候,扰动了i的值。 但是,如果用let定义: var arr = []; for(let i = 0 ; i < 10 ; i++){ //i实际上定义在了循环体中 arr[i] = function(){ console.log(i); } } arr[6](); //6 如果用let来引导循环,出了循环体就真的没有定义了 for(let i = 0; i < 10 ; i++){ //相当于在这里定义了i } console.log(i); //报错 不存在变量声明的提升: console.log(a); //报错 let a = 10;
let会引发暂时性死区(面试常考):
在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
var m = 10; function fun(){ m = 20; //报错。函数在预解析阶段会预读所有的语句,发现了let语句,所以就将这个函数变为了一个m的暂时性死区,此时m不允许在let前被赋值。 let m; console.log(m); } fun();
暂时性死区是一个特别好的性质,比如我们之前特别经典的题目:
var m = 10; function fun(){ m = 20; var m = 30; } fun(); console.log(m); //输出10,因为函数里面有变量声明的提升,所以改变的都是局部变量m,没有改变全局变量m的值。 但是如果用let: var m = 10; function fun(){ m = 20; //语句有错误!因为这里是暂时性死区,不能对m在let之前操作。 let m = 30; } fun(); console.log(m); //报错
const命令表示定义一个常量,不能被更改的量:
const pi = 3.14; console.log(pi); pi = 3.1415; //报错
但是可以指向一个引用类型值,对这个引用类型值的操作是允许的,但是不能允许指向别的值:
const arr = ["白板","幺鸡","二条"]; arr.push("三筒"); console.log(arr); // 合法,["白板","幺鸡","二条","三筒"]; arr = ["王","王","2","2","2","2"]; //报错,因为arr是常量。 如果要冻结对象,用Object.freeze() const arr = Object.freeze(["白板","幺鸡","二条"]); console.log(arr); //合法 arr.push("三桶"); //报错!因为对象已经被冻结! Object.freeze()只能冻结一层: var obj = Object.freeze({"a" : 1 , "b" : 2 , "c" : ["J","Q","K"]}); obj.a = 44; //没有修改成功 obj.c.push("A"); //A成功推入了数组,因为freeze只能冻结1层 console.log(obj); //{"a" : 1 , "b" : 2 , "c" : ["J","Q","K","A"]}; let和const定义的变量不会成为window对象的属性, let a = 100; var b = 200; const c = 300; alert(window.a); //undefined alert(window.b); //200 alert(window.c); //undefined
二、ES6中的解构
数组的解构:
var [a,b,c] = ["白板","幺鸡","二条"]; console.log(a); console.log(b); console.log(c);
对象的结构:
var {name,age} = {name :"老王" , age : 12}; console.log(name); console.log(age);
数组的结构用[],对象的解构用{}。此时一定要区分它数数组,还是解构。区分方法很简单,看它是在赋值还是在取值。等号左边的,都是解构,等号右边的,都是数组或者对象。
来看一个...运算符,
先看:
var [a,b,c] = ["白板","幺鸡","二条","三饼","四筒"]; console.log(a); console.log(b); console.log(c);
如果给c加上一个...运算符:
var [a,b,...c] = ["白板","幺鸡","二条","三饼","四筒"]; console.log(a); console.log(b); console.log(c);
...必须出现在尾巴上,这个叫做rest运算符,俗称“尾巴”解构。
var [a,...b,c] = ["白板","幺鸡","二条","三饼","四筒"]; //报错
函数的参数也可以解构:
function fun([a,b]){ console.log(a + b); } fun([4,7]);
我靠!这不就是将一个数组传入了函数,函数自动帮我拆开数组了么!
想起了一个东西,apply!
类似于:
function fun(a,b){ console.log(a+b); } fun.apply(null,[4,7]); //11
apply基本上下岗了,以后可以使用[]在形参列表中,表示自动解构。
再来看一个,函数的形参列表中也可以使用...运算符:
function fun(...arr){ let sum = 0; for(let i = 0 ; i < arr.length ; i++){ sum += arr[i]; } console.log(sum); } fun(1,2,3,4);
此时这个函数就是计算所有实参的和,原来要使用arguments对象,此时arguments基本也下岗了。
形参列表中还可以有对象的自动解构语法:
function fun({shuxue,yuwen,yingyu}){ console.log(shuxue + yuwen + yingyu); } var xiaoming = {"name" : "小明" , "age" : 12 , "shuxue" : 10 , "yuwen" :20 , "yingyu" :30}; fun(xiaoming); //60,在计算各个科目的总分。 对于对象来说,还有一个k:v的解构模式,特别重要。 let obj = {"a" : 1 , "b" : 2}; let { a : n , b : m} = obj; console.log(n); //1 console.log(m); //2 console.log(a); //报错 console.log(b); //报错
冒号右边的变量才真正的被赋值,冒号左边的变量表示对象的属性。
:在结构中很好用,哲学是从对象中取一个属性,但是又要给这个属性改名。比如对象中的属性叫做shuxue,我们想取得这个值,并且用math变量来接收:
let xiaoming = {"name" : "小明" , "age" : 12 , "shuxue" : 10 , "yuwen" :20 , "yingyu" :30}; let {shuxue : math} = xiaoming; console.log(math); ...很好用: function fun(a,b,c){ console.log(a); console.log(b); console.log(c); } var arr = [1,2,3]; 我们想让控制台输出1、2、3,也就是将数组中的数组“打开”传入函数。我们之前: fun.apply(null,arr); 现在: fun(...arr);
三、ES6中的字符串、数组的增强
原来,我们只能用A.indexOf(B)来判定A字符串中含不含有B字符串。
现在有了:
includes(), startsWith(), endsWith() includes():返回布尔值,表示是否找到了参数字符串。 startsWith():返回布尔值,表示参数字符串是否在源字符串的头部。 endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部。 let str = "我爱北京天安门"; console.log(str.includes("北京")); //true console.log(str.startsWith("北京")); //false console.log(str.endsWith("天安门")); //true repeat()重复多少次 var str = "★".repeat(5); console.log(str);
`是一个新增加的运算符,表示模板字符串。
var a = 10; var b = "高兴"; var c = "手机"; var str = `好高兴啊,我买了一个${c},花了${a}元,我很${b}啊!`; console.log(str);
可以有效减少斩断连接!
可以有轻微运算:
var str = `好高兴啊,我买了一个${c},花了${a + shui}元,我很${b}啊!`;
不能有复杂语法:
$(if()) `中的东西可以依法换行,不需要斩断连接。 let imgurl = "logo.jpg" let str = ` <ul> <li> <a href=""> <img src="${imgurl}" alt=""/> </a> </li> </ul> `; console.log(str)
来看数组的改变,Array.from()可以将类数组对象变为数组:
let obj = { "0" : "白板", "1" : "幺鸡", "2" : "二筒", length : 3 }; let arr = Array.from(obj); console.log(arr);
Array.of方法用于将一组值,转换为数组
var arr = Array.of(1,2,3); console.log(arr);
寻找数组中是否有某项find()、findIndex(),里面要放置回调函数
需要注意的是,里面的回调函数的三个参数分别是项、编号、数组本身。机理是JS会测试每一个项目,返回第一个返回true的项。
var arr = [3,4,5,34,34,324,342,43,23,30,60,45,34,53]; var item = arr.find(function(value,index,arr){ if(value % 5 == 0 && value % 6 == 0){ return true; } }); console.log(item); //30
返回第一个返回true的下标项,用findIndex,如果没有一个项目返回true的函数,此时就会显示-1。
var arr = [3,4,5,34,34,324,342,43,23,30,60,45,34,53]; var item = arr.findIndex(function(value,index,arr){ if(value % 5 == 0 && value % 6 == 0){ return true; } }); console.log(item); //9
增加了一种数组的遍历方法,叫做for of遍历。通常配合arr.entries()和arr.key()来使用。
let arr = ["白板","幺鸡","二条","三饼","四筒"]; for(let v of arr){ console.log(v); }
let arr = ["白板","幺鸡","二条","三饼","四筒"]; for(let [k,v] of arr.entries()){ console.log(k,v); }
includes()返回一个布尔值,判断数组中是否有某个项。现在终于不用遍历整个数组来验证某一个项目是否存在了。
let arr = ["白板","幺鸡","二条","三饼","四筒"]; console.log(arr.includes("二条"));