ES6语法重点介绍
箭头函数以及声明特点
ES允许使用箭头 =>定义函数
//声明一个函数(旧)
let fn=function () {
}
//声明一个函数(ES6)
let fn1=(a,b)=>{
return a+b;
}
let result = fn1(1,5);
console.log(result);
- 特性(this是静态的)
this是静态的,this始终指向函数声明时所在作用域下的this的值(所在作用域下的对象,也就是函数的外层的this)
call方法可以改变函数内部this的值(但是箭头函数声明的无法被改变)
<script>
function getName() {
console.log(this.name);
}
let getName1=()=>{
console.log(this.name);
}
window.name=`尚硅谷`;
const school={
name:'ATGUIGU'
}
//普通调用
getName();
getName1();
//call 方法调用
getName.call(school);
getName1.call(school);
</script>
- 不能作为构造函数去实例化对象
- 不能使用arguments变量(arguments可以用来在函数中保存实参)
箭头函数的简写
- (1)省略小扩号,当形参有且只有一个的时候
let add=n=>{
return n+n;
}
console.log(add(9))
- (2)省略花括号,当代码体只有一条语句的时候,此时return必须省略,而且语句的执行结果就是函数的返回值
<script>
let pow=(n)=> n*n;
console.log(pow(9));
</script>
箭头函数的实践与应用场景
需求(点击div两秒后变色)
不用箭头函数,this指向的对象就是谁调用它对象就是谁,如果没有调用那么this就是window,需要在外层把当前对象赋给另外对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>let</title>
<style>
div{
width: 200px;
height: 200px;
background: #b1e2ff;
}
</style>
</head>
<body>
<div id="add"></div>
<script>
let ad = document.getElementById('add');
ad.addEventListener('click',function () {
let _this=this;
setTimeout(function () {
//修改背景颜色 this
_this.style.background='red';
},2000)
})
</script>
</body>
</html>
- 使用箭头函数
// let add = document.getElementById(‘add’);
这样是不行的因为,它所在的作用域下没有this,而它的父作用域是window(不像普通函数一样谁调用它,this就是谁)
let add = document.getElementById('add'); add.addEventListener('click',()=>{ })
<script>
let add = document.getElementById('add');
add.addEventListener('click',function () {
//定时器
//此时this具有块级作用域,会在父级块级区域找this
setTimeout(()=>{
this.style.background='black';
},2000)
})
</script>
- this是window
<script>
let add = document.getElementById('add');
add.addEventListener('click',()=>{
console.log(this)
})
</script>
- this是调用它的相关dom
<script>
let add = document.getElementById('add');
add.addEventListener('click',function () {
console.log(this)
})
</script>
筛选出偶数
- 不用箭头函数
<script>
let array=[6,2,36,4,8,9];
const resut=array.filter(function (item) {
if (item%2===0){
return true;
}else {
return false;
}
})
console.log(resut);
</script>
- 使用箭头函数
<script>
let array=[6,2,36,4,8,9];
const result=array.filter(item=>item%2===0);
console.log(result);
</script>
箭头函数适合与this无关的回调,定时器,数组的方法回调
不适合与this有关的回调,事件回调,对象的方法
函数参数的默认值设置
ES6允许给函数参数赋值初始值
形参初始值,具有默认值的参数,一般位置要靠后
<script>
function add(a,b,c=10) {
return a+b+c;
}
let result = add(1,2);
console.log(result);
</script>
与结构赋值结合
<script>
//与结构赋值杰哥
function connect({host,username,password,port}) {
console.log(host);
console.log(username);
console.log(password);
console.log(port);
}
//方法的调用
connect({
host:'localhost',
username:'root',
password:'root',
port:'3306'
})
</script>
- 形参赋值
如果实参传过来了就用实参的,否则就用初始过的形参的值
<script>
//与结构赋值杰哥
function connect({host=`127.0.0.1`,username,password,port}) {
console.log(host);
console.log(username);
console.log(password);
console.log(port);
}
//方法的调用
connect({
username:'root',
password:'root',
port:'3306'
})
</script>
rest参数
ES6引入rest参数,用于获取函数的实参,用来代替arguments
不用rest参数
<script>
function fn() {
console.log(arguments);
}
fn('白芷','阿娇','思慧');
</script>
使用rest参数
rest参数必须要放到参数列表最后
<script>
function date(...args) {
//args是一个数组
console.log(args);//filter some every map
}
date('白芷','阿娇','思慧');
</script>
rest参数必须要放到参数列表最后
<script>
function date(a,b,...args) {
//args是一个数组
console.log(a);
console.log(b);
console.log(args);//filter some every map
}
date('白芷','阿娇','思慧','白泽');
</script>
扩展运算符
扩展运算符有对象的扩展运算和数组的扩展运算
【…】扩展运算符能将数组转换为逗号分隔的参数序列
<script>
const array=['aa','bb','cc','dd','ee'];
function chunwan() {
console.log(arguments);
}
chunwan(...array)
</script>
扩展运算符的应用
- 数组的拼接
不使用扩展运算符
<script>
const array=['aa','bb','cc'];
const array1=['dd','ee'];
let concat = array.concat(array1);
console.log(concat);
</script>
- 使用扩展运算符
<script>
const array=['aa','bb','cc'];
const array1=['dd','ee'];
const result=[...array,...array1];
console.log(result);
</script>
数组的克隆
<script>
const array=['aa','bb','cc'];
const ya=[...array];
console.log(ya);
</script>
将伪数组转为真正的数组
<script>
const divs=document.querySelectorAll('div');
const divArr=[divs];
console.log(divArr);
</script>
对象的扩展运算
<script>
const person={name:'zzq',age:25,address:'上海'};
const a={...person};
console.log(a.name);
console.log(a.age);
console.log(a.address);
</script>
Symbol的介绍与创建
Symbol是由ES6规范引入的一项新特性,它是一种新的基础数据类型,它的功能类似于一种标识唯一性的ID。通常情况下,我们可以通过调用Symbol()函数来创建一个Symbol实例:
ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。它是JavaScript语言的第七种数据类型,是一种类似于字符串的数据类型。
- Symbol的值是唯一的。用来解决命名冲突的问题
- Symbol值不能与其他数据进行运算
- Symbol定义的对象属性不能使用for…in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名
- Symbol的创建第一种
<script>
//创建Symbol
let s = Symbol();
console.log(s, typeof s);
let s2 = Symbol(`尚硅谷`);
let s3 = Symbol(`尚硅谷`);
//相当于编号不同
console.log(s === s3); //false
</script>
- Symbol的创建第二种(函数对象)
<script>
let symbol = Symbol.for(`尚硅谷`);
let symbo2 = Symbol.for(`尚硅谷`);
console.log(symbol === symbo2);//true
</script>
JavaScript数据类型
USONB
- u: undefined
- s:string symbol
- o:object
- n: null number
- b: boolean
Symbol的使用场景
Symbol就是给对象添加属性和行为,表示独一无二
- 第一种写法
<script>
//向对象中添加方法 up down
let game={
name:'俄罗斯方块',
up:function () {
},
down:function () {
}
}
//声明一个对象
let methods={
up:Symbol(),
down:Symbol()
}
//添加到对象中
game[methods.up]=function () {
console.log(`我可以改变形状`);
}
game[methods.down]=function () {
console.log(`我可以快速下降!!`);
}
console.log(game);
</script>
- 第二种写法
<script>
let youxi={
name:`狼人杀`,
[Symbol('say')]:function () {
console.log(`我可以发言`);
},
[Symbol('zibao')]:function () {
console.log(`我可以自爆`);
}
}
console.log(youxi);
</script>
Symbol的内置对象
- Symbol.hasInstance
当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法
<script>
class person{
static [Symbol.hasInstance](parm){
console.log(parm);
console.log(`我被用来检测类型`);
}
}
let o={
name:`zzq`
};
console.log(o instanceof person)
</script>
迭代器
工作原理
ES6创造了一种新的遍历命令for…of 循环
for…of循环
for…of循环遍历出数组的键值,类型Java中的加强for循环
<script>
const xiyou=[`唐僧`,`孙悟空`,`猪八戒`,`沙僧`];
for (let v of xiyou) {
console.log(v);
}
</script>
for…in循环遍历出数组的键值
<script>
const xiyou=[`唐僧`,`孙悟空`,`猪八戒`,`沙僧`];
for (let str in xiyou) {
console.log(str);
}
</script>
自定义遍历数据
<script>
//声明一个对象
const banji={
name:`终极一班`,
stus:[
`aa`,
`bb`,
`cc`,
`dd`,
`ee`,
],
//自定义遍历数据
[Symbol.iterator](){
//定义索引变量
let index=0;
return{
next:()=>{
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提供的一种异步编程解决方案,语法行为与传统函数完全不同
使用
生成器其实就是一个特殊的函数
异步编程:纯回调函数 noded fs ajax mongodb
<script>
//要加*号
function * gen(){
console.log(`hello a`);
}
let iterator = gen();
console.log(iterator.next());
</script>
可以使用yield
yield相当于函数代码的分隔符
<script>
function * gen(){
yield `aab`;
console.log(111);
yield `bbb`;
console.log(222);
yield `ccc`;
console.log(333);
}
let iterator = gen();
iterator.next();
iterator.next();
iterator.next();
iterator.next();
for (let v of gen()) {
console.log(v);
}
</script>
生成器函数的参数传递
next方法在调用的时候可以传入实参
第二次next传入的参数会作为第一个yield的整体返回结果
下一次next传入的参数都会作为上一个yield的返回结果
<script>
function * gen(arg){
console.log(arg);
let one = yield 111;
console.log(one);
let two = yield 222;
console.log(two);
let three = yield 333;
console.log(three);
}
//获取迭代器对象
let iterator = gen('AAA');
console.log(iterator.next());
//第二次传入的会作为第一个yield的整体返回结果
console.log(iterator.next('BBB'));
console.log(iterator.next(`CCC`));
console.log(iterator.next(`DDD`));
</script>
生成器函数的实例(异步任务)
1s后控制台输出111 2s后输出 222 3s后输出 333
- 不使用生成器函数
<script>
setTimeout(()=>{
console.log(111);
setTimeout(()=>{
console.log(222);
setTimeout(()=>{
console.log(333);
},3000)
},2000)
},1000)
</script>
- 使用生成器函数
<script>
function one() {
setTimeout(()=>{
console.log(111);
iterator.next();
},1000)
}
function two() {
setTimeout(()=>{
console.log(222);
iterator.next();
},2000)
}
function three() {
setTimeout(()=>{
console.log(333);
iterator.next();
},3000)
}
//生成器函数
function* gen() {
yield one();
yield two();
yield three();
}
//调用生成器函数
let iterator = gen();
iterator.next();
</script>
模拟获取 用户数据 订单数据 商品数据
<script>
function getUsers() {
setTimeout(()=>{
let data='用户数据';
//第二次调用next把数据传入到next参数中会作为第一个yield的整体返回
iterator.next(data);
},1000)
}
function getOrders(userdata) {
setTimeout(()=>{
let data='订单数据';
console.log(userdata+data);
//第三次调用
iterator.next(data);
},1000)
}
function getGoods(orderData) {
setTimeout(()=>{
let data='商品数据';
//第四次调用
iterator.next(data);
},1000)
}
function * gen() {
let userData = yield getUsers();
let orderData = yield getOrders(userData);
let goodsData = yield getGoods(orderData);
}
//调用生成器函数
let iterator = gen();
//第一次调用
iterator.next();
</script>
Promise介绍与基本使用
Promise是ES6引入的异步编程的新解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或者失败的结果。
- 1、Promise构造函数:Promise(excutor){}
- 2、Promise.prototype.then方法
- 3、Promise.prototype.catch方法
Promise里又两个参数方法,执行resolve后Promise对象是成功,执行reject后Promise对象是失败
<script>
//实例化Promise对象
const p = new Promise(function (resolve, reject) {
setTimeout(function () {
let data='数据库中的数据';
//调用resolve后p的状态会变成成功
resolve(data);
//调用reject后p的状态会变成失败
let err='数据读取失败';
reject(err);
},1000)
});
//调用promise的then方法(里面有两个方法参数成功和失败,第一是成功参数是value,第二个是失败参数是reason)
//调用resolve是成功回调调用第一个方法,调用reject是失败会调用第二个方法
p.then(function (value) {
console.log(value);
},function (reason) {
console.log(reason);
})
</script>
Promise封装读取文件
Node Js执行js文件
不使用Promise进行封装
//1、引入fs模块
const fs=require('fs');
//2、调用方法读取文件
fs.readFile('../resources/aa.md',(err,data)=>{
//如果失败则抛出错误
if (err) throw err;
//不出错 则输出data
console.log(data.toString());
});
使用Promise进行封装
//3、使用Promise进行封装
let p = new Promise((resolve, reject) => {
const fs=require('fs');
fs.readFile('./resources/aa.md',(err, data) => {
if (!err){
//p的状态是成功
resolve(data);
}else {
//p的状态是失败
reject(err);
}
});
});
p.then(function (value) {
console.log(value.toString());
},function (reason) {
console.log(`${reason}读取失败`);
});
Promise封装Ajax
原生Ajax
//1、创建对象
const xhr=new XMLHttpRequest();
//2、初始化
xhr.open('GET','https://aip.apiopen.top/getJoke');
//3、发送
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.error(xhr.status);
}
}
}
使用Promise进行封装
const p=new Promise((resolve, reject) => {
//1、创建对象
const xhr=new XMLHttpRequest();
//2、初始化
xhr.open("GET","https://www.baidu.com");
//3、发送
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);
})
Promise.prototype.then方法
then方法的返回结果是Promise对象,对象状态由Promise的执行结果决定
//嵌套调用
p.then(value => {},reason => {}).then(value => {},reason => {});
读取三个文件并把它们进行拼接
不用Promise
可以发现变量名重复,回调地狱
const fs=require('fs');
fs.readFile('../resources/aa.md',(err, data) => {
fs.readFile('../resources/bb.md',(err, data1) => {
fs.readFile('../resources/cc.md',(err, data2) => {
console.log(data + data1 + data2);
});
});
});
使用Promise
const fs=require('fs');
//使用Promise实现
const p=new Promise((resolve, reject) => {
fs.readFile('../resources/aa.md',(err, data) => {
resolve(data.toString());
});
});
//嵌套then
p.then(value => {
return new Promise((resolve, reject) => {
fs.readFile('../resources/bb.md',(err, data) => {
resolve([value,data]);
});
})
}).then(value => {
return new Promise((resolve, reject) => {
fs.readFile('../resources/cc.md',(err, data) => {
//压入
value.push(data);
resolve(value);
});
})
}).then(value => {
console.log(value.join('\r\n'));
})
Promise对象的catch方法
和then的区别是没有第一参数
const p=new Promise((resolve, reject) => {
setTimeout(()=>{
//设置p对象的状态
reject('出错啦!')
},1000)
})
p.catch(reason => {
console.warn(reason);
})
集合介绍与API
ES6提供了新的数据结构Set(集合)。它类似于数组。但成员的值都是唯一的。集合实现了iterator接口。所以可以使用【扩展运算符】和【for of】进行遍历。它本身是一个对象。类似Java中的set集合也是自动去重的
set
- 集合的属性和方法:
- size 返回集合的元素个数
- add 增加一个新元素,返回boolean值(所有类型)
- delete 删除元素,返回boolean值
- has 检测集合中是否包含某个元素,返回boolean值
<script>
//声明一个set(不初始化)
let s = new Set();
//声明一个初始化的set
let s2 = new Set(['aa','bb','cc','dd','aa']);//会去重
console.log(s);
console.log(s2);
//元素的个数
let size = s2.size;
console.log(size);
//添加元素
let add = s2.add('dagdsag');
console.log(add);
//删除元素
console.log(s2.delete('dagdsag'));
console.log(s2);
//检测
let has = s2.has('aa');
console.log(has);
//清空clean
s2.clear();
console.log(s2);
</script>
- 使用for…of进行遍历
<script>
//声明一个初始化的set
let s2 = new Set(['aa','bb','cc','dd','aa']);//会去重
//遍历
for (let s of s2) {
console.log(s);
}
</script>
set实践
数组去重
通过扩展运算符【…】可以把集合转成数组
//数组去重,先把数组扔到set中,然后通过扩展运算符把集合转成数组
let arr=[1,6,5,4,6,5,4,1,3,2,1,6,5,4];
let result=[...new Set(arr)];
console.log(result);
交集
<script>
//交集,一般先去重
let arr1=[1,2,3,4,5,5,1,1];
let arr2=[1,3,5];
let result=[...new Set(arr1)].filter(item=>{
//把第二个数组变集合
let numbers = new Set(arr2);
if (numbers.has(item)){
return true;
}else {
return false;
}
})
console.log(result);
</script>
并集
<script>
//并集
let arr1=[1,2,3,4,5,5,1,1];
let arr2=[1,3,5];
let numbers = [...arr1,...arr2];
let numbers1 =[...new Set(numbers)];
console.log(numbers1);
</script>
Map介绍与API
ES6提供了Map数据结构。它类似于对象,也是键值对的集合,但是键的范围不限于字符串,各种类型的值都可以当作键。Map也实现了iterator接口,所以可以使用【扩展运算符】和【for of】进行遍历。Map的属性和方法。
- size 返回Map的元素个数
- set 增加一个新元素,返回当前Map
- get返回键名对象的键值
- has 检测Map中是否包含某个元素,返回boolean值
- clean 清空集合,返回undefined
<script>
//声明Map
let map = new Map();
//添加元素
let a = map.set('key1',45644);
let a1 = a.get('key1');
//给map添加值(值是方法)
map.set('change',()=>{
console.log('值也可以是一个方法');
})
let key={
jian:'键可以是一个对象'
}
//给map设置key(key是一个对象)
map.set(key,['aa','bb','cc','dd'])
//通过key获取值
console.log(map.get(key));
//获取map的元素个数
console.log(map.size);
//删除
let delete1 = map.delete(key);
console.log(map.get(key));
//for of进行遍历
for (let mapElement of map) {
console.log(mapElement);
}
</script>
for of遍历的时候,map的每个元素都包含两个部分,键和值
class介绍和初体验
ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6的class可以看作知识一个语法糖,它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
- class声明类
- constructor定义构造函数初始化
- extends继承父类
- super调用父级构造方法
- static 定义静态方法和属性
- 父类方法可以重写
- ES5之前初始化一个类
使用函数对象
<script>
//手机
function Phone(brand, price) {
this.brand=brand;
this.price=price;
}
//添加方法
Phone.prototype.call=function () {
console.log('I can call');
}
//实例化对象
let hauwei = new Phone('华为',5999);
hauwei.call();
console.log(hauwei);
</script>
- 使用Class进行初始化
class Phone {
//构造方法 名字不能修改
constructor(brand,price) {
this.brand=brand;
this.price=price;
}
//方法必须使用该语法,不能使用ES的对象完整形式
call(){
console.log('我可以打电话');
}
}
let phone = new Phone('1+',555);
console.log(phone);
//对象调用方法
// console.log(phone.call());
class静态成员
类似于Java的静态方法和静态变量,不过不同于Java的是,ES6的静态成员只能由Class进行调用,实例化对象无法调用
- 使用ES5进行设置静态成员和方法
<script>
//手机
function Phone(brand, price) {
this.brand=brand;
this.price=price;
}
//添加方法
Phone.prototype.call=function () {
console.log('I can call');
}
//静态属性和方法
Phone.name='dag';
Phone.aa=function () {
console.log('dasg');
}
//实例化对象
let hauwei = new Phone('华为',5999);
hauwei.call();
console.log(hauwei);
console.log(Phone.name);
console.log(Phone.aa());
</script>
使用ES6进行定义
<script>
class Phone{
constructor(brand,price) {
this.brand=brand;
this.price=price;
}
call(){
console.log('打电话');
}
//静态属性
static name='手机';
//静态方法
static change(){
console.log('苹果手机');
}
}
let phone = new Phone('dag',44600);
console.log(Phone.name);
console.log(Phone.change());
</script>
构造函数继承
ES5之前的继承
<script>
function Phone(brand, price) {
this.brand=brand;
this.price=price;
}
Phone.prototype.play=function () {
console.log('我可以打电话');
}
//智能手机
function SmartPhone(brand, price, color, size) {
//这儿的this是smartPhone的实例对象
Phone.call(this,brand,price);
this.color=color;
this.size=size;
}
//设置子级构造函数的原型
SmartPhone.prototype=new Phone();
//有和无区别不大
SmartPhone.prototype.constructor=SmartPhone;
//声明子类的方法
SmartPhone.prototype.photo=function () {
console.log('我可以拍照');
}
SmartPhone.prototype.playGame=function () {
console.log('可以玩游戏');
}
const chuizi=new SmartPhone('锤子',4500,'黑色','5.5inch');
console.log(chuizi);
</script>
ES6 class的类继承
<script>
class phone{
constructor(brand,price) {
this.bran=brand;
this.price=price;
}
//父类的成员属性
callone() {
console.log('我可以打电话!!!');
}
}
//子类继承父类
class smartPhone extends phone{
constructor(brand,price,color,size) {
super(brand,price);//类似于 Phone.call(this,brand,price);
this.color=color;
this.size=size;
}
phone(){
console.log('拍照');
}
playGame(){
console.log('玩游戏');
}
}
let phone1 = new smartPhone('xiaomi',9222,'黑色','4.7inch');
console.log(phone1);
</script>
子类对父类方法的重写
<script>
class phone{
constructor(brand,price) {
this.bran=brand;
this.price=price;
}
//父类的成员属性
callone() {
console.log('我可以打电话!!!');
}
}
//子类继承父类
class smartPhone extends phone{
constructor(brand,price,color,size) {
super(brand,price);//类似于 Phone.call(this,brand,price);
this.color=color;
this.size=size;
}
phone(){
console.log('拍照');
}
playGame(){
console.log('玩游戏');
}
//重写父类的方法
callone(){
console.log('子类重写的父类的callone方法');
}
}
let phone1 = new smartPhone('xiaomi',9222,'黑色','4.7inch');
//callone调用的是子类重写的父类方法,所以只能调用子类的callone方法(不然重写没有意义)
console.log(phone1.callone());
</script>
class中的getter和setter设置
<script>
//get 和 set
class Phone{
get price(){
console.log('价格属性被获取了');
return this.newVal;
}
set price(newVal){
console.log('价格属性被修改了');
this.newVal=newVal;
}
}
//实例化对象
let s=new Phone();
//调用set方法
s.price='free';
//调用get方法
console.log(s.price);
</script>