ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准。因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015。
也就是说,ES6就是ES2015。
虽然目前并不是所有浏览器都能兼容ES6全部特性,但越来越多的程序员在实际项目当中已经开始使用ES6了。所以就算你现在不打算使用ES6,但为了看懂别人的你也该懂点ES6的语法了…
在我们正式讲解ES6语法之前,我们得先了解下Babel。
Babel
Babel是一个广泛使用的ES6转码器,可以将ES6代码转为ES5代码,从而在现有环境执行。大家可以选择自己习惯的工具来使用使用Babel,具体过程可直接在Babel官网查看
最常用的ES6新特性
let,const,class,extends,super,arrow function,template string,destructuring,default,rest arguments
1.let定义变量,const定义常量,var和let的区别是块级作用域和循环添加事件的使用
<1>不可重复定义变量
var a = 1;
let a = 1;
const c = 3;
- 1
- 2
- 3
在ES5中可以对一个变量重复定义,但在ES6中不行
var a = 1;
var a = 2;
console.log("a:" + a);
- 1
- 2
- 3
输出的结果是2,后面把前面的变量覆盖
那么,我们看一下ES6中的let会发生什么情况呢?
let b = 3;
let b = 4;
console.log("b:" + b);
- 1
- 2
- 3
在控制台上报了一个错误:
Uncaught Error: Module build failed: C:/Users/xiaohua/Desktop/webpack/webpack-demo4-ES6/src/app.js: Duplicate declaration “b”
意思就是说重复声明
突然想到一个问题
如果这样声明一个变量var,再声明一个let 会怎样呢?一试便知
var c = 5;
let c = 5;
console.log("c:" + c);
- 1
- 2
- 3
如果这样的话,还是和上面一样报错
<2>let有块级作用域,而var没有
var d = 1;
if(true){
var d = 2;
}
console.log("d:" + d);
- 1
- 2
- 3
- 4
- 5
想必这个输出的是2,因为没有块级作用域,所以输出的是2
如果换做let的话就不一样了哦
let e = 3;
if(true){
let e = 2;
}
console.log("e:" + e); //3
- 1
- 2
- 3
- 4
- 5
<3>对于循环点击事件中索引值的获取在ES5中可以用this和闭包解决,有了ES6的let,妈妈再也不用担心我获取不到索引值了。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>主页</title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
ul,li{
list-style: none;
}
#box{
width: 100%;
height: auto;
}
#box li{
width: 100%;
height: 30px;
margin-bottom: 10px;
background: #9ff;
}
</style>
</head>
<body>
<div id="result"></div>
<ul id="box">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul>
<script type="text/javascript">
let ulList =document.getElementsByTagName('li');
//方法1:
for(var i=0;i<ulList.length;i++){
ulList[i].index = i;
ulList[i].onclick = function(){
var index = this.index;
console.log(index);
}
}
//方法2:用let就可以直接获取
for(let i=0;i<ulList.length;i++){
ulList[i].onclick = function(){
console.log(i);
}
}
</script>
</body>
</html>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
2.class,extens的使用
许多人一直说javascript语法中没有类语法,不利于大型面向对象的项目开发。”千呼万唤始出来”,ES6终于加入了类语法,但实质上还是对原型继承的一种封装,写起来会比较直观,我们知道OO的三大特性:封装,继承,多态。下面主要ES6的类语法进行介绍。
定义类
class Animal{
constructor(){
this.type = 'animal';
}
says(say){
console.log(this.type + ' say ' + say );
console.log(this); //dog{type: "dog"}
}
}
new Animal().says("cat"); //cat
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
用extends关键字实现继承
class Dog extends Animal{
constructor(color){
super(); //调用父类的constructor()
this.type = 'dog';
}
}
new Dog().says('hello'); //Dog say hello
- 1
- 2
- 3
- 4
- 5
- 6
- 7
ES5面向对象实现了类的功能,但没有类这一概念
ES6出现了类,这一概念
新的class写法让原型对象的写法更加清晰,更像面向对象编程的语法
一个Ainimal类
class Animal{
constructor(name,type){
this.name = name;
this.type = type;
}
getName(){
console.log("===this.name===:" + this.name);
console.log("===this.type===" + this.type);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
new Animal(‘cat’,”猫猫”).getName();
new Animal() 其实是创建一个实例
这个是在实例中传参数
你也可以给getName()方法传参数
class Person{
constructor(name){
this.name = name;
//console.log(this);
}
getName(say){
console.log(this.name + " say " + say);
}
}
new Person('xiao').getName("hello");
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
类中constructor方法外的所有方法其他实例对象都可以共享
继承
class People extends Person{
constructor(name){
super();
this.name = name;
}
}
new People('xiaohua').getName('ni hao');
- 1
- 2
- 3
- 4
- 5
- 6
- 7
继承了父类 相当于继承了父类所有的属性和方法
上面super 是获取父类this对象的
如果把 this.name = name;放在super前面时,会报错,因为没有获取到this对象
3.arrow function
ES5的写法
function add(a,b){
return a + b;
}
console.log(add(2,3)); //5
- 1
- 2
- 3
- 4
ES6的写法:
var add = (a,b)=>{
return a+b;
}
console.log(add(2,3));
- 1
- 2
- 3
- 4
4.template string
当我们要写入大段的html内容的到文档中时
var result = document.getElementById("result");
var string = document.getElementById("string");
var as = 1;
var sb = 2;
- 1
- 2
- 3
- 4
//之前是这样写的
result.innerHTML=(
"There are <b>" + as + "</b>" +
"items in your basket," +
"<em>" + sb + "</em> are on sale!"
)
- 1
- 2
- 3
- 4
- 5
ES6这样写的
string.innerHTML=(`
There are <b>${as}</b>items
in your basket,<em>${sb}</em>
are on sale;
`)
- 1
- 2
- 3
- 4
- 5
$("#result").append(
"There are <b>"+as+"</b>"+
"items in your basket," +
"<em>" + sb + "</em> are on sale!"
)
- 1
- 2
- 3
- 4
- 5
$("#string").append(`
There are <b>${as}<b>items
in your basket,<em>${sb}</em>
are on sale;
`)
- 1
- 2
- 3
- 4
- 5
用反引号来标识起始,用${}来引用变量,
而且所有的空格和缩进都会被保留在输出中
5.destructuring
ES6按照一定的模式,在数组和对象中提取值,对变量进行赋值,
这被称为解构(Destructuring)
看下面的例子
let cat = "maomi";
let dog = "gougou";
let zoo = {cat:cat,dog:dog}
console.log(zoo); //{cat: "maomi", dog: "gougou"}
- 1
- 2
- 3
- 4
用ES6完全可以按照下面这样写:
let cat = "maomao";
let dog = "gougou";
let zoo = {cat,dog};
console.log(zoo); //Object {cat: "maomao", dog: "gougou"}
- 1
- 2
- 3
- 4
//反过来可以这么写
let dogs = {type:'animal',many:2};
let {type,many} = dogs;
console.log(type,many); // animal 2
- 1
- 2
- 3
6.default rest
default 很简单,意思就是默认值
可以看下面的例子,调用animal()方法时忘了传参数,
传统的方法是加上一句 type = type || “cat” 来指定默认值。
function animal(type){
type = type || "cat";
console.log(type);
}
animal(); //cat
//如果ES6可以直接这样写
function animals(type = "dog"){
console.log(type);
}
animals();
animals("cat");
//rest方法也很简单
function animalss(...types){
console.log(types);
}
animalss('cat','dog','fish'); //(3) ["cat", "dog", "fish"]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
ES6原生提供了Promise对象
所谓Promise就是一个对象,用来传递异步操作的信息,它代表某个未来才会知道结果的
事件(通常是一个异步操作),并且这个事件提供统一的API,可进一步处理。
Promise对象有以下两个特点
1.对象的状态不受外界影响。
Promise代表一个异步操作,有3种状态:
Pending(进行中)
Resolved(已完成,又称Fulfilled)
Reject(已失败)
只有异步操作的结果,可以决定当前是哪一种状态,
任何其他操作都无法改变这个状态
2.一旦状态改变就不会再变
任何时候都可以得到这个结果
Promise状态改变只有两种可能
从Pending –> Resolved
从Pending –> Reject
只要这两种状态发生了,就凝固了,不会再变了,会一直保持这个结果。
就算改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果
这与事件完全不同,
事件的特点是:你错过了它,再去监听是得不到结果的
有了Promise对象,就可以将异步操作以同步操作的流程表达出来,
避免层层嵌套的回调函数。此外,Promise提供了统一的接口,
使得控制异步操作更加容易*/ES6原生提供了Promise对象
所谓Promise就是一个对象,用来传递异步操作的信息,它代表某个未来才会知道结果的
事件(通常是一个异步操作),并且这个事件提供统一的API,可进一步处理。
Promise对象有以下两个特点
1.对象的状态不受外界影响。
Promise代表一个异步操作,有3种状态:
Pending(进行中)
Resolved(已完成,又称Fulfilled)
Reject(已失败)
只有异步操作的结果,可以决定当前是哪一种状态,
任何其他操作都无法改变这个状态
2.一旦状态改变就不会再变
任何时候都可以得到这个结果
Promise状态改变只有两种可能
从Pending –> Resolved
从Pending –> Reject
只要这两种状态发生了,就凝固了,不会再变了,会一直保持这个结果。
就算改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果
这与事件完全不同,
事件的特点是:你错过了它,再去监听是得不到结果的
有了Promise对象,就可以将异步操作以同步操作的流程表达出来,
避免层层嵌套的回调函数。此外,Promise提供了统一的接口,
使得控制异步操作更加容易*/
var promise = new Promise(function(resolve,reject){
if(/*如果异步操作成功*/){
resolve(value);
}else{
reject(error);
}
})
promise.then(function(value){
//success
},function(value){
//failed
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
Promise构造函数接受一个函数作为参数,该参数的两个参数分别是resolve方法和reject方法
如果异步操作成功,则用resolve方法将Promise对象的状态,从[未完成]变为成功
function timeout(ms){
//ES5的写法
return new Promise(function(resolve,reject){
})
//ES6的写法
return new Promise((resolve,reject)=>{
setTimeout(resolve,ms,'done');
})
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
timeout(100).then((value) =>{
console.log(value);
})
- 1
- 2
- 3
上面代码中,timeout方法返回一个Promise实例,表示一段时间之后才会发生结果
过了指定的时间(ms 参数)以后,Promise实例的状态就会变为Resolved,
就会触发then方法绑定的回到函数。
Promise新建之后就会立即执行
let promise = new Promise(function(resolved,reject){
console.log("promise");
resolved();
})
promise.then(function(){
console.log("Resolved");
})
console.log("Hi");
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
在js世界里,所有代码都是单线程的
由于这个缺陷,导致js的所有网络操作,浏览器事件,都必须是异步执行。
异步执行可以通过回调函数实现。
简单的Promise例子:
生成一个0-2的随机数,如果小于1,则等待一段时间后返回成功
否则返回失败
function test(resolve,reject){
var timeout = Math.random() * 2;
console.log("set timeout to:" + timeout + " second");
setTime(function(){
if(timeout < 1){
console.log("call resolve()……");
//set timeout to:0.12384566863093394 second
resolve("200 ok");
}else{
console.log("call reject()……");
//失败ReferenceError: setTime is not defined
reject("timeout in" + timeout + " second");
}
},timeout * 2000)
}
//这个test有两个参数,两个参数都是函数,如果执行成功我们将调用
//resolve("200 resolved")
//如果执行失败
//我们调用reject("timeout in" + timeout + "second");
var p1 = new Promise(test);
var p2 = p1.then(function(result){
console.log("成功 "+ result);
}).catch(function(reason){
console.log("失败 " + reason);
});
function add(a,b){
return a + b;
}
console.log(add(2,3));
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/markdown_views-ea0013b516.css">
</div>