ES6(ECMAScript 6)学习——一文搞懂ES6
学习完JavaScript和vue后快速学习ES6新特性及其语法,es6是JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。
ES6学习——一文搞懂ES6
es6介绍
ES全称EcmaScript,是脚本语言的规范,而平时经常编写的EcmaScript的一种实现,所以ES新特性其实就是指JavaScript的新特性。
为什么要学习ES6
1.ES6版本变动内容最多,具有里程碑意义。
2.ES6加入了许多新的语法特性,编程实现更简单,高效
3.ES6是前段开发的趋势,就业必备
ES6-let变量声明以及声明特性
声明变量:
let特性
- 变量不能重复声明
- 块级作用域【全局作用域,函数作用域,eval作用域】
- 不存在变量提升【:代码在执行之前的时候会提前收集变量以及函数,并赋值初始值null和undefined】let不能在变量声明之前去使用,而var可以在被声明之前被使用。
- 不影响作用域链
const的声明及其特点
变量声明【声明常量】
const的使用注意
- 一定要赋初始值
- 潜规则,一般常量使用大写
- 常量值不能修改
- 块级作用域
5.对于数组和对象的元素修改,不算做对常量的修改,不会报错
ES6变量的结构赋值
ES6允许按照一定模式从数组和对象中提取值,对变量进行赋值
- 数组的解构
- 对象的解构
为什么要进行对象解构?
先看代码:
属性解构使用的比较少,方法解构用的比较多,如果不用方法解构,每次都需要写“zhao.xiaopin()”的形式,就比较重复,那么可以进行对象的解构,调用方式就不需要在前面写“zhao.xxx”的形式;
什么情况下使用方法的解构:
新特性的产生就是为了让开发者更加方便,发现有重复的地方,就想办法把它去掉,如果遇到方法频繁调用,这个时候就可以想到解构赋值用上,让代码更加简洁。
ES6模板字符串
es6引入新兴的声明字符串的方式
- es6字符串声明
- 特性一:内容中可以直接出现换行符
es6之前出现换行符会出现报错【语法错误】
es6出现后不报错使用 “``” 即可解决语法报错问题。
- 特性二:变量拼接
es6对象的简化写法
es6允许直接在大括号里面直接写入变量和函数,作为对象的属性和方法,简化程序员书写代码的步骤。
- 变量形式简化对象写法
- 方法声明简化
es6之前对象方法的繁琐写法
es6之后对象方法的简化写法
ES6箭头函数以及声明特点
es6允许使用 [箭头] (=>) 定义函数
- 使用原始方法声明一个函数和使用箭头函数声明一个方法
- 箭头函数声明的特性,和之前的函数有什么区别?
一、this是静态的,this始终是指向函数声明时所在作用域下的this的值,箭头函数的this值是静态的,无论使用使用任何方式去调用它,它的this始终是指向函数在声明时所在作用域下的那个this值。
直接调用:
call方法调用:可以改变函数内部this的值,下面的结果可以看出call不能改变箭头函数中this的指向。
二、箭头函数不能作为构造函数来实例化对象
三、不能使用arguments变量【函数内部特殊的变量arguments,用来保存实参】
四、箭头函数的简写,两种情况
第一种:是省略小括号,当形参有且只有一个的时候可以省略。
第二种:是省略花括号,当代码体只有一条语句的时候,此时return必须省略,而且语序的执行结果就是函数的返回值。
箭头函数使用注意事项:
一、 箭头函数适用于this无关的回调,定时器,数组方法的回调
二、 箭头函数不适合与thi有关的回调,事件回调,对象的方法
es6函数参数的默认值设置
es6中允许给函数参数赋值初始值
-
形参的初始值
es6中形参少传递一个出现NaN结果
es6给函数赋初始值,如果不传递这个参数,默认值是初始值
注意点:既有默认值的参数,一般位置要靠后(潜规则) -
与解构赋值结合使用
如果传了用传的参数,如果没有传使用设置的默认值。
es6中rest参数
es6引用rest参数,用于获取函数的实参,用来代替arguments【获取函数在调用时所有的实参】
- es5获取实参数的方式【返回的对象】
- es6中的rest参数【返回的是数组】
返回数组就可以使用"filter",some every,map,提高了对参数处理的灵活程度。 - 注意:如果参数有多个,rest参数必须要放到参数的最后。
错误使用:
正确使用:
es6扩展运算符介绍
【…】扩展运算符能将【数组】转换成逗号分割的【参数序列】。
- 例子
不使用…传递,传递数组
使用…传递
扩展运算符的应用
- 数组的合并
- 数组的克隆
- 将伪数组转为真数组
es6-Symbol的介绍与创建
- symbol的介绍
es6引入了一种新的原始数据类型symbol,独一无二的值,他是javascript语言的第七种数据类型,是一种类似于字符串的数组类型。 - symbol的特点
一、 symbol的值是唯一的,用来解决命名冲突问题。
二、symbol的值不能与其他数据进行运算。
三、symbol定义的对象属性不能使用for…in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名
- 创建symbol
第一种创建方式:
第二种创建方式:其中括号内只是symbol的标志
第三种方式:【Symbol.for()】,symbol.for是一个全局的symbol表,如果有了就访问对应对象,如果没有就创建。
es6-对象添加symbol类型的属性
使用symbol添加对象和属性,我们可以很快速的很安全的把对象加入game里面,不会破坏原有的属性和方法。
- 第一种添加方法
- 第二种添加
ES6-Symbol的内置值
除了定义自己使用的Symbol值以外,ES6还提供了很多内置的Symbol值,指向语言内部使用的方法。
- Symbol.hasInstance
- isConcatSpreadable
es6-迭代器
迭代器是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据解构只要部署iterator接口,就可以完成遍历操作。
- es6创造了一种新的遍历命令for … of循环,lterator接口主要供for…or消费
- 原生具备iterator接口的数据可用for of遍历,Array,Arguments,Set,map,string,typeArray,NodeList
- 工作原理
a. 创建一个指针,指向当前数据结构的起始位置。 b. 第一次调用对象的next方法,指针自动指向数据结构的第一个成员, c. 接下来不断调用next方法,指针一直往后移动,知道只想最后一个成员。 d. 每调用next方法返回一个包含value和done属性的对象 **注意:需要自定义遍历数据的时候要想到迭代器**
- for…of循环【输出键值】
- for…in循环【输出键名】
迭代器应用-自定义遍历数据
根据迭代器的工作原理自定义迭代器遍历数据
<script>
//声明一个对象
const banji = {
name:"终极一班",
stus:['小明','小天','小吴','小王',],
[Symbol.iterator](){
//索引变量
let index = 0;
//指向
let _this = this;
return {
next:function(){
if(index<_this.stus.length){
const result = {value:_this.stus[index],done:false}
//下标自增
index++;
//返回结果
return result;
}else{
return {value:undefined,done:true}
}
}
}
}
}
//遍历这个对象
for(let v of banji){
console.log(v);
}
</script>
效果:
es6-生成器函数声明与调用
生成器函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同,其实就是一个特殊的函数,用来异步编程,之前用的是纯回调函数
node \fs \ ajax\mongodb
- 声明与调用方式:
- 生成器可以使用yield语句
yield可以算作函数代码的分隔符
yield语句可以作为分割符使用,使用next调用
- 使用for-of遍历生成器
- 生成器的原理输出解释yield的作用:
ES6生成器函数的参数传递
生成器调用的next是可以传递实参的,而这个实参数就是这个yield语句整个返回结果。
- 整体函数传参
- next方法也是可以传参的,而且这个参数将作为上一个yeild语句的返回结果,第二次调用返回第一个yeild语句的整体返回结果,。。。
es6生成器函数实例
异步编程:文件操作,网络操作(ajax,request)数据库操作
实例:1s输出111 ,2s输出222,3s输出333
层层回调,会变成回调地狱
上面代码会进入回调地狱,下面就不行
实例二、模拟获取,用户数据,订单数据,商品数据
调用:
es6-promise学习与使用
es6-promise介绍与基本使用
promise是ES6引入的异步编程的新解决方案,语法上市promise是一个构造函数,用来封装异步操作并可以获取奇成功或失败的结果【解决回调地狱问题】
- Promise构造函数 :
Promise {excutor}{ }
Promise.prototype.then
方法Promise.prototype.catch
方法
1. 实例化Promise对象
Promise对象有三个状态,初始化,成功,失败
实例化promise对象:
//实例化Promise对象【三个状态:初始化,成功,失败】
const p = new Promise(function(resolve,reject){
setTimeout(() => {
let data = "数据库中的用户数据"
//resolve调用
resolve(data);
}, 1000);
});
调用成功和失败都会执行promise.then的方法,then的方法有两个参数,两个参数都是函数类型的值,每个函数都有一个形参,成功的执行then的第一个函数,失败的执行第二个执行参数,两个函数的形参分别是value和reason,成功的叫做value,失败的叫做reson。
调用then代码:
/*
调用成功,就会调用promise对象的then方法,
then方法接受两个参数,
两个参数都是函数类型的值,每个函数都有一个形参,成功的叫做value,失败的叫做reason
调到resolve代表成功,读取状态成功,then就会执行第一个回调函数代码
如果读取状态失败,调用带有
*/
p.then(
function(value){
console.log(value);
},
function(reason){
}
)
成功调用输出:
读取失败的例子:
const p = new Promise(function(resolve,reject){
setTimeout(() => {
//
let data = "数据库中的用户数据"
let err = "读取数据库失败"
//resolve调用
reject(err)
}, 1000);
});
p.then(function(value){
console.log(value);
},function(reason){
console.log(reason);
})
es6-promise封装读取文件
原生js输出文件内容【请求文件内容属于异步】
//引入fs模块
const fs = require('fs');
//调用方法读取文件
fs.readFile('./resources/1.md',(err,data)=>{
//如果失败则抛出错误
if(err) throw err;
//如果没有出错,则输出内容
console.log(data.toString());
})
效果:
使用promise封装读取文件:
//3.使用promise封装
const p = new Promise(function(resolve,reject){
fs.readFile("./resources/1.md",(err,data)=>{
//判断读取失败
if(err) reject(err);
//如果成功
resolve(data)
})
})
p.then(
function(value){
console.log(value.toString());
},
function(reason){
console.log(reason);
})
效果:
es6-promise封装Ajax请求
- 原生Ajax请求数据
<script>
//接口地址:https://api.apiopen.top/getJoke
//创建对象
const xhr = new XMLHttpRequest();
//初始化
xhr.open("GET","https://api.apiopen.top/getJoke");
//发送
xhr.send();
//4.绑定时间,处理响应结果
xhr.onreadystatechange = function(){
//判断
if(xhr.readyState === 4){
//判断响应状态吗 200-299
if(xhr.status >= 200 && xhr.status < 300){
//表示成功
console.log(xhr.response);
}else{
//如果失败
console.log(xhr.status);
}
}
}
</script>
请求成功效果:
请求失败结果:
2. Promise进行封装Ajax代码
<script>
//接口地址:https://api.apiopen.top/getJoke
const p = new Promise((resolve,reject)=>{
//创建对象
const xhr = new XMLHttpRequest();
//初始化
xhr.open("GET","https://api.apiopen.top/getJoke");
//发送
xhr.send();
//4.绑定时间,处理响应结果
xhr.onreadystatechange = function(){
//判断
if(xhr.readyState === 4){
//判断响应状态吗 200-299
if(xhr.status >= 200 && xhr.status < 300){
//表示成功
resolve(xhr.response)
}else{
//如果失败
reject(xhr.status);
}
}
}
});
//指定回调
p.then(
function(value){
console.log(value);
},
function(reason){
console.log(reason);
})
</script>
成功效果:
失败效果:
处理方式不一样,原来是在回调函数里面处理成功和失败的结果,promise实在异步任务的后面通过then来指定回调,结构清晰,也不会产生回调地狱的问题。
es6-Promise.prototype.then方法
-
then返回结果:返回结果是由执行函数的回调结果来决定的,如果回调函数中返回的结果是 ||promise类型的属性,状态为成功,返回值为对象的成功值。
-
then返回非Promise对象
//创建promise对象
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
//resolve("请求成功")
reject("请求失败")
},1000)
});
//调用 then方法
const result = p.then(value =>{
console.log(value);
return value;
},reason =>{
console.log(reason);
return reason;
})
console.log(result);
不写return
返回undefined
结果:
3. then返回Promise对象
then返回Promise对象,then中promise的状态就决定了then方法返回的一个对象的状态,then中Promise的失败就决定了then方法返回的一个失败的状态。
//创建promise对象
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("请求成功")
//reject("请求失败")
},1000)
});
//调用 then方法
const result = p.then(value =>{
return new Promise((resolve,reject)=>{
resolve('ok')
})
},reason =>{
console.log(reason);
})
console.log(result);
4. then抛出错误
【如果抛出错误的话,这个状态也是一个失败的Promise状态,错误的值就是抛出的值】
//创建promise对象
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("请求成功")
//reject("请求失败")
},1000)
});
//调用 then方法
const result = p.then(value =>{
//抛出错误
throw new Error("出错啦")
},reason =>{
console.log(reason);
})
console.log(result);
效果:
既然then的方法可以返回promise对象,所以说then方法可以链式调用,链式调用[then方法指定回调的时候是可以只指定一个的,可以通过链式调用来改变回调地狱的问题]
格式:
p.then(value=>{
//异步任务
},reason=>{
//异步任务
}).then(value=>{
//异步任务
},reason=>{
//异步任务
})
es6-promise实践练习-多个文件内容读取
//回调地狱容易重名,很不容易被发现
- 使用回调地狱方式来做
//引入fs模块
const fs = require("fs")
fs.readFile('./resources/1.md',(err,data)=>{
fs.readFile('./resources/2.md',(err,data1)=>{
fs.readFile('./resources/3.md',(err,data2)=>{
let result = data+"\r\n"+data1+"\r\n"+data2
console.log(result);
});
});
});
上面代码可以发现 ,回调地狱容易重名,很不容易被发现。
Promise实现:
//使用promise来实现
const p = new Promise((resolve,reject)=>{
fs.readFile("./resources/1.md",(err,data)=>{
resolve(data);
})
})
p.then(value=>{
return new Promise((resolve,reject)=>{
fs.readFile("./resources/2.md",(err,data)=>{
resolve([value,data]);
});
});
}).then(value=>{
return new Promise((resolve,reject)=>{
fs.readFile("./resources/3.md",(err,data)=>{
//压入
value.push(data);
resolve(value)
});
});
}).then(value=>{
console.log(value.join('\r\n'));
})
es6-Promise对象catch方法
catch用来指定promise失败的一个回调
第一种方式代码:
<script>
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
//设置p对象的状态为失败,并且设置失败的值
reject("出错啦")
})
})
p.then(function(value){
},function(reason){
console.error(reason);
})
</script>
效果:
第二种方式代码:
<script>
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
//设置p对象的状态为失败,并且设置失败的值
reject("出错啦")
})
})
p.catch(function(reason){
console.warn(reason);
})
</script>
es6-集合介绍与API
set介绍
ES6提供了新的数据结构Set(集合)。它类似于数组,但成员的值都是唯一的集合实现了iterator接口,所以可以使用[扩展运算符]和[for…of…]进行遍历
集合的属性和方法:
1)size: 返回集合的元素个数
2)add: 郑加一个新元素,返回当前集合
3)delete: 删除元素,返回boolean值
4)has:检测集合中是否包含某个元素,返回boolean值
简单通过代码了解Set:
//声明一个set
let s = new Set();
//可以写入可迭代数据,可以去重
let s2 = new Set(['大事儿','小事儿','坏事儿','小事儿','很多事儿','大事儿'])
console.log(s,typeof s);
console.log(s2);
效果:
集合属性和方法的介绍代码和效果
//元素个数
let s2 = new Set(['大事儿','小事儿','坏事儿','小事儿','很多事儿','大事儿'])
console.log(s2.size);
//向集合里添加新的元素
s2.add("喜事儿")
console.log("集合添加后有:"+s2.size+"个",s2);
//删除元素
s2.delete("坏事儿")
console.log("集合删除后有:"+s2.size+"个",s2);
//检测【检测集合中有没有该元素】
console.log(s2.has('喜事儿'));
//可以使用for...of...遍历
for(let v of s2){
console.log(v);
}
//清空集合
s2.clear();
console.log(s2);
效果:
es6-集合实践
已经知道两个数组:
let arr = [1,2,3,4,5,4,3,2,1,5,4,5,8,9,54,4,1]
let arr2 = [54,1,3,4,6,9,8]
- 数组去重
//1.数组去重
let result = [...new Set(arr)]
console.log(result);
2. 两个数组求交集
//2.交集
let arr2 = [54,1,3,4,6,9,8]
let result2 = [...new Set(arr)].filter(item=>{
let s2 = new Set(arr2)
if(s2.has(item)){
return true
}else{
return false
}
})
console.log(result2);
//简化版求交集
let result3 =[...new Set(arr)].filter(item=>new Set(arr2).has(item))
console.log(result3);
3. 两个数组求并集
//3.并集
let result4 =[...new Set([...arr,...arr2])]
console.log(result4);
效果:
4. 求两个数组的差集【交集的逆运算】
//4.差集
let result5 = [...new Set(arr)].filter(item=>{
let s2 = new Set(arr2)
if(!s2.has(item)){
return true
}else{
return false
}
})
let result6 =[...new Set(arr)].filter(item=>!new Set(arr2).has(item))
console.log(result5);
console.log(result6);
效果:
es6-Map的介绍与API
es6提供了map数据结构,它类似于对象,也是键值对的集合,但是"键"的范围不限于字符串,各种类型的值(包括对象)都可以当做键,map也实现了iterator接口,所以可以使用【扩展运算符】和【for…of…】进行遍历,map的属性和方法:
- size 返回map的元素个数
- size 正价一个新元素,返回当前的map
- get 返回键名对象的键值
- has 检测map中是否包含某个元素,返回bollean值
- clear 清空集合,返回undefined
声明一个Map并且添加
//声明 Map
let m = new Map();
//添加元素
m.set('name','吴又可');
m.set('change',function(){
console.log("无用的方法");
});
console.log(m);
map添加第二种方法
//声明 Map
let m = new Map();
//添加元素
m.set('name','吴又可');
m.set('change',function(){
console.log("无用的方法");
});
let key = {
school : "sgg"
};
m.set(key,['北京','上海','广州']);
console.log(m);
效果:
map的其他API
//添加
m.set(key,['北京','上海','广州']);
//删除
m.delete('name')
console.log(m);
//获取
console.log(m.get('change'));
console.log(m.get(key));
//遍历
for(let v of m){
console.log(v);
}
//清空
m.clear();
es6-class类
es6提供了更接近传统语言的写法,引入了Class类这个概念,作为对象的模板,通过class关键字,可以定义类,基本上,es6的class可以看做只是一个语法糖,它的绝大部分功能,es5都可以做到,新的class写法只是让对象的圆形的写法更加清晰,更像面向对象编程的语法而已。
-
知识点:
(1) class声明类
(2) constructor定义构造函数初始化
(3) extends继承父类
(4) static定义静态方法和属性
(5) super调用父级构造方法
(6) 父类方法可以重写 -
回顾Es6类的使用
// 手机
function Phone(brand,price){
this.brand = brand;
this.price = price;
}
//添加方法
Phone.prototype.call = function(){
console.log("我可以打电话");
}
//实例化对象
let Huawei = new Phone('华为',5999);
Huawei.call();
console.log(Huawei);
使用效果:
3. es6的class的使用
// class
class Phone{
//构造方法,名字不能修改,当实例化的时候会自动执行
constructor(brand,price){
this.brand = brand;
this.price = price;
}
//方法必须使用该语法,不能使用es5的对象完整形式
call(){
console.log("我可以打电话");
}
}
let onePlus = new Phone("huawei",4999);
console.log(onePlus);
es6的class使用效果
es6中Class里面的静态成员
es5中的静态成员
es5中实例对象和函数对象的属性是不相通的,实例对象的属性和构造函数的原型对象相通,实例对象的隐式原型指向构造函数的原型对象
function Phone(){
}
Phone.name = "手机";
Phone.change = function(){
console.log("我可以改变世界");
}
Phone.prototype.size = "5.5inch"
let nokia = new Phone();
console.log(nokia.name);
console.log(nokia.size);
npkia.change();
效果:
未完待续~
更多推荐
所有评论(0)