2020.12.9 18:13
ES6
01.变量:let、const
var 可以重复声明、函数级作用域、变量提升、变量
let 不能重复声明、块级作用域、没有变量提升的概念、暂时性死区、变量
const 不能重复声明、块级作用域、没有变量提升的概念、暂时性死区、常量
02.解构赋值
es6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这称为解构
let [a,b,c]=[10,100,'h']
等价于let a=10 let b=100 let c='h'
-
如果变量多余,相当于声明不赋值。如果数据多余,对变量没有影响
let [a,b,c,d]=[10,100,'h']
console.log(a,b,c,d);//10,100,'h',undefined
-
对象的解构赋值 使用的是{},对象的解构与数组的解构有一个重要的不同,
-
数组的元素是按次序排列的,数组解构中,变量的值由所处的位置决定。对象的属性没有次序,变量必须与属性同名才可以,才可以取到正确的值。
var stu={ name:'za',age:112};
let {name,age,hobby}={stu};
console.log(name,age.hobby);//za,112,undefined
hobby相当于声明了没赋值 -
字符串的解构按照字符串的顺序依次赋值
let [x,y,z]='hello';
console.log(x,y,z);//h,e,l
-
类数组的对象的解构赋值
let {length:len}='zsh';
console.log(len);//3
-
函数的解构赋值:函数的解构赋值类似于数组的解构解构
function add([a,b]){console.log(a+b);}
add([3,4]);//7
add('34');//34
字符串拼接,相当于把字符串3赋给了a,字符串4赋给了b
03.参数扩展
默认参数
function(a=50,b=10){}
- 调用时传入值那参数的值就是传入的值
- 调用时不传值那参数的值就是默认值
剩余参数
...变量名
- 用来获取函数的多余实参,只能放置在形参结尾,不能放置开始或者中间
- 剩余参数是一个数组
function add(a,b,...c){}
add(5,10,15,20,25,30)
a=5,b=10,c=[15,20,25,30]
04.字符串的扩展
``反引号
模板字符串
- 在变量和常量拼接的时候使用 整个字符串使用
${变量}
标签模板
- ``可以跟在一个函数后面,该函数将被调用来处理这个模板字符串。这被称为模板标签功能
05.数组的扩展
- 创建数组:
Array.of()
Array.of()对new Array()的扩展 。不论输入什么,都代表的是数组元素 - 类数组转化为数组:
Array.from()
类数组:一定要严格按照格式来写 属性名是0 1 2 并且一定要有length。如果转化为了数组,最终的长度是length的值 - 查找元素:
find和findIndex
数组.find(function(n代表数组元素){条件})得到的结果是第一个符合条件的数组元素的值
数组.findIndex(function(n代表数组元素){条件})得到的结果是第一个符合条件的数组元素的下标。从左到右寻找 如果找不到结果是-1。 - 操作数组:
es5:splice(删除/替换/插入)/map(映射)/reduce(求和)/forEach(循环)/fliter(过滤)
es6:copyWithin(替换)
数组.splice(参数1,参数2,参数3)
开始的位置(下标) ,删除的个数 ,插入的元素
数组.map(function(value))
value:当前元素的值
数组.reduce(function(total,value){})
total:初始值, 或者计算结束后的返回值。value:当前元素
数组.forEach(function(item,index){})
item:当前元素。index:下标
数组.filter(function(){条件})
数组.copyWithin(参数1,参数2,参数3)
替换开始的位置(下标) ,复制开始的位置,复制结束的位置 含开始不含结束
使用copyWithin注意:
- 只是替换,复制的元素的数量。复制的如果多余需要替换的。数组不会扩展,只会替换应有的数量
- 值可以是负值。从右到左。从-1开始
- 负值的时候,一定要保证开始的位置,小于结束的位置
06.箭头函数
a.方便(不能有function关键字
和函数名
)
- 如果只有一个参数,
()
可以省略 - 如果函数体中只有一句简单的代码,
{}
可以省略 - 如果函数体中只有一个return,
return和{}
都可以省略
b.修正this
- 箭头函数中的this指向的是定义的时候所在的对象,而不是使用的时候所在的对象
call、apply、bind
不能修改箭头函数中this的指向- 箭头函数不可以当做构造函数使用,也就是说,不可以使用new命令,否则会抛出错误
箭头函数,使用注意点
- 箭头函数中的this指向的是定义的时候所在的对象,而不是使用的时候所在的对象
- 箭头函数不可以当做构造函数使用,也就是说,不可以使用new命令,否则会抛出错误。
- 箭头函数内部,没有
arguments
,只能使用剩余参数
07.JSON
- JSON.stringify() 将json转为字符串
- JSON.parse() 将字符串转为json
08.get和set
get方法 获取的值的时候会自动调用 一定要加返回值
set方法 设置值的时候会自动调用 实参是通过等于号赋值
class Circle{
constructor(){
this.r=10;
}
get acr(){
return Math.PI*this.r*this.r;
}
set acr(){
this.r=value;
}
}
var c=new Circle();
// 调用的是get方法
console.log(c.acr);
// 调用的是set方法
c.acr=1;
console.log(c.acr);
09.class
es6类可以说是构造函数加原型的复合。
es6类的概念,只是"语法糖"。es6实现的关于类的大多数功能都可以通过es5方法实现。
类就是封装事物
class 类名{
constructor(){
放置属性
//也可以在此放置方法
}
放置方法1//(方法之间不加符号,加符号会报错)
放置方法2
放置方法...
}
书写在constructor中的方法,
- 每一次实例对象的时候,都会重新生成一个新的方法。(效率偏低)
- 针对于每一个对象,执行的方法都是一样的,这个时候就会造成资源浪费(实例对象的方法)
放置在类中的方法,相当于放置在了类名.prototype内部
(原型的方法)
放在constructor
里的都是自有方法,和constructor
同级的都是继承来的
类的constructor
- construtor方法是类的默认方法,一个类必须有constructor方法。
- 如果没有显示定义,一个空的constructor方法会被默认添加
- 通过new命令生成实例对象的时候,自动调用该方法
constructor默认返回的是实例对象。完全可以指定返回另外一个对象
constructor(color){return new Array(10,20,30);}
返回一个数组,可以使用数组的方法
10.继承
Class之间通过extends关键字实现继承。比在es5中通过原型链实现继承,要清晰和方便。更偏向传统编程语言
super关键字
- super关键字,它在这里表示父类的构造函数,用来新建父类的this对象
- 子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。
- 实例化对象的时候,把实参的值,赋值给了constructor,如果constructor没有该属性传递不过来,直接书写属性会报错
- super必须要放到构造函数this的前面
- super调用父类中的构造函数,再把参数传给父类
- super调用父类中的普通函数
11.继承相关的一些问题
1.判断子类实例对象的属性是自有还是继承来的
- super相当于把父级的属性一一复制过来,也就成了自有属性,属性是自有的,不继承
- 如果父类中有某个属性,子类中constructor和super中不写这个属性,那这个属性依旧存在,但是值是undefined
2.原型链相关问题
- 继承是无限制的,可以有很多层
3.判断父类是否存在于子类的原型链中
- 原型链的概念在类的继承中生效
4.super
继承为什么要加super?
- 在子类的constructor中必须要有super关键字,如果不写,会报错
- 子类的this关键字根据super方法创建
- 子类实例对象的构建,是基于父类实例进行加工。只有super方法才可以返回父类实例
12.静态方法
- 类中的方法前面如果加了sataic关键字,该方法就是静态方法
- 静态方法只能通过类名直接调用。
- 静态属性指的是类本身有的属性,通过类名.属性名直接调用。不需要实例化对象调用
- 静态方法和静态属性可以被子类继承
最典型的静态方法:Math.random()
最典型的静态属性:Math.PI
私有方法
在es6的提案,提到了如果方法名以_开始,默认只能在类中调用,不能被继承或者被实例对象使用
13.Promise
Promise 对象
- 用同步的方式来书写异步代码
- Promise 让异步操作写起来,像在写同步操作的流程,不必一层层地嵌套回调函数
- 改善了可读性,对于多层嵌套的回调函数很方便
- 充当异步操作与回调函数之间的中介,使得异步操作具备同步操作的接口
Promise 也是一个构造函数
- 接受一个回调函数作为参数,回调函数里面是异步操作的代码
- 返回的p就是一个 Promise 实例对象
- 所有异步任务都返回一个 Promise 实例对象
- Promise 实例对象有一个then方法,用来指定下一步的回调函数
Promise怎么用
通过Promise请求数据后调用.then()
方法
let p=new Promise((resolve,reject)=>{
$.ajax({url:'data/arr.txt',dataType:'json',
success(data){
resolve(data);//成功后执行resolve
},
error(error){
reject(err);//失败后执行reject
}
});
}
p.then(data=>{//请求成功执行,实际上就是resolve
console.log(`请求成功`);
console.log(data);
},
()=>console.log(`请求失败`)//请求失败执行,实际上就是reject
);
Promise.all([])方法
- 受一个数组作为参数
- 将多个Promise对象实例包装,生成并返回一个新的Promise实例
- promise数组中所有的promise实例都变为resolve的时候,该方法才会返回,并将所有结果传递results数组中
- promise数组中任何一个promise为reject的话,则整个Promise.all调用会立即终止,并返回一个reject的新的promise对象
var p1 = Promise.resolve(1),
p2 = Promise.resolve(2),
p3 = Promise.resolve(3);
Promise.all([p1, p2, p3]).then(function (results) {
console.log(results); // [1, 2, 3]
});
Promise.race([])方法
- 接受一个数组作为参数
- Promse.race就是赛跑的意思,哪个结果获得的快,就返回那个结果
- 不管结果本身是成功状态还是失败状态
链式操作
通过then方法处理带逻辑性的事情,例如通过return将数据返回,再调用then方法进行逻辑判断,再根据判断的结果决定执行哪些事
14.generator
generator(生成器)
- generator(生成器)是一个函数
- generator 函数是 ES6 提供的一种异步编程解决方案
- generator 函数有多种理解角度。从语法上,首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态
generator函数和普通函数的区别
书写格式上:
- 普通函数:
function generator(参数){代码...}
- 生成器函数:
function* generator(参数){代码...}
注意* - 函数体内部使用yield语句,定义不同的内部状态(yield在英语里的意思就是“产出”)
执行过程中
- 普通函数:普通函数在执行过程中,如果没有遇到return语句(函数末尾如果没有return,就是隐含的return undefined),控制权无法交回被调用的代码
- 白话理解:普通函数在执行过程中不能停止
- 生成器函数:生成器函数在执行过程中除了return语句,还可以用yield返回多次
- 白话理解:生成器函数在执行过程中可以停止(等待某件事情完成),再执行(剩余部分)
调用上:
- 调用Generator函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对
下一步,必须调用遍历器对象的next方法 - Generator函数是分段执行的,yield语句是暂停执行的标记,而next方法可以恢复执行
Generator函数是分段执行的,yield语句是暂停执行的标记,而next方法可以恢复执行
Generator函数使用:
//generator函数
function *generator(a,b){
alert(a);
yield;
alert(b);
}
let genObj=generator(5,10);//函数名()不能直接调用 实际上返回了一个对象
console.log(genObj instanceof Object);//true
genObj.next();//调用一次只会弹出a,因为遇到yield停止了
genObj.next();//再调用一次才会弹出b
yield
- yield可以穿参数也可以返回
1.传参:
给yeild之前的部分传参(和普通函数穿参一样)
function *show(参数1,参数2){ 参数1和参数2在这里使用 yield ··· }
let gen=show(参数1,参数2);
给yeild之后的部分传参(通过next)
function *show(参数1,参数2){ 参数1和参数2在这里使用 yield 参数3,参数4 }
let gen=show(参数1,参数2);
gen.next()
注意第一次调用next传参无效gen.next(参数3,参数4)
总结:第一次调用next无法给yield传参,第二次调用才能成功传参,给yield之前的部分传参和给普通函数传参相同
2.返回:
function* show(){
alert('a');
yield 12;
alert('b');
//如果最后一步想要返回值只能return
//return 55;
}
let gen=show();
let res1=gen.next();
console.log(res1);//{value:12,done:false} done,完成的,值为false表示函数未执行完
let res2=gen.next();
//不写return 55输出{value:undefined,done:true} 值为true表示函数已执行完
//写return 55输出{value:55,done:true}
console.log(res2)
*号
如果函数前漏掉 *
- 就是普通函数
- 如果有yield会报错, ReferenceError: yield is not defined
- yield 只能在Generator函数内部使用