类(class)
class 的本质是 function。
它可以看作一个语法糖,让对象原型的写法更加清晰、更像面向对象编程的语法。
1.类的声明不会被提升,和let const 一样,有临时性死区
2.类的所有代码全都是在严格模式中执行
3.类的所有方法都是不可枚举的
4.类的所有方法都无法当成构造函数直接使用
5.类的构造器必须使用new 来调用
不可重复声明
class Person{
constructor(job,name,age,sex){
this.job = job;
this.name = name;
this.age = age;
this.sex = sex;
}
print(){
console.log('工作:',this.job)
console.log('姓名:',this.name)
console.log('年龄:',this.age)
console.log('性别:',this.sex)
}
}
const a = new Person("程序猿","zhansan",30,"nan");
console.log(a)
a.print()
1.可以写成计算属性名
2.getter 和 setter
getter取值的时候必须走进来 get
setter 设置值得之后必须走进来 set
get set 控制的属性不在原型上
// ES5的写法
Object.defineProperty(this,"age", {
set(age){
},
get(){
}
})
3.静态成员
static 添加静态成员
4.字段初始器(es7)
使用static 添加字段初始器,添加的是静态成员;
没有使用,则位于对象上。
箭头函数在字段初始器位置上,指向当前对象
5.类表达式
const A = class{ //匿名类,类表达式,类在js中本身就是表达式
a = 1;
b = 2;
}
const a = new A();
console.log(a)
6.类的继承
如果两个类 A 和 B, B是A,则A和B形成继承关系
extends
通过 extends 实现类的继承。
class Child extends Father { ... }
super
class Father {
test(){
return 0;
}
static test1(){
return 1;
}
}
class Child extends Father {
constructor(){
super();
}
}
1.直接当成函数调用,表示父类的构造
如果定义了constructor 并表示这个是子类,则必须在constructor的第一行手动调用父类的构造函数
如果说子类不写constructor,则会有默认的构造器,自动去调用父类的构造器
2.super如果说当成对象使用,则表示父类的原型
Symbol(符号描述)
ES6 引入了一种新的原始数据类型 Symbol ,表示独一无二的值,最大的用法是用来定义对象的唯一属性名。
Symbol 函数栈不能用 new 命令,因为 Symbol 是原始数据类型,不是对象,可以接受一个字符串作为参数,为新创建的 Symbol 提供描述,用来显示在控制台或者作为字符串的时候使用,便于区分。
const syb1 = Symbol(); //创建了一个符号
const syb2 = Symbol("asdfsdf");
const syb3 = Symbol("asdfsdf");
console.log(syb2 === syb3);//false
1.没有字面量的写法
2.新的数据类型,typeof返回的是symbol
3.每次去调用Symbol函数得到的符号永远不会相等,不管符号描述是否相同
4.符号可以作为对象的属性名使用,这种属性名叫符号属性(Symbol 作为对象属性名时不能用.运算符,要用方括号)
5.符号属性不能被枚举
(如果要读取到一个对象的 Symbol 属性,可以通过 Object.getOwnPropertySymbols() 和 Reflect.ownKeys() 取到。)
Symbol.for()
共享符号
Symbol.for(“符号描述”) 如果符号描述相等,则可以得到同一个符号
const syb1 = Symbol("abc");
const syb2 = Symbol.for("abc");
const syb3 = Symbol.for("abc");
console.log(syb1 === syb2) //false
console.log(syb2 === syb3) //true
Symbol.keyFor()
Symbol.keyFor() 返回一个已登记的 Symbol 类型值的 key ,用来检测该字符串参数作为名称的 Symbol 值是否已被登记。
let yellow1 = Symbol.for("Yellow");
Symbol.keyFor(yellow1); // "Yellow"
promise
是异步编程的一种解决方案。
从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。
Promise 异步操作有三种状态: pending resolved rejected
pending:挂起(等待) 处于未决阶段,表示事情还是在挂起,最后的结果没有出来
resolved:已处理 处于已决阶段,表示整个事情已经出现结果,并且可以按照正常的逻辑进行下去的结果
rejected:已拒绝 处于已决阶段,表示整个事情已经出现结果,并且是一个无法按照正常逻辑进行下去的结果
Promise 对象只有:从 pending 变为 fulfilled 和从 pending 变为 rejected 的状态改变。只要处于 fulfilled 和 rejected ,状态就不会再变了即 resolved(已定型)。
resolved 这是一个正常的已决状态,后续处理表示为 thenable
rejected 这是一个非正常的已决状态,后续处理表示为 catchable
状态的缺点
无法取消 Promise ,一旦新建它就会立即执行,无法中途取消。
如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。
当处于 pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
then 方法
then 方法接收两个函数作为参数,第一个参数是 Promise 执行成功时的回调,第二个参数是 Promise 执行失败时的回调,两个函数只会有一个被调用。
Promise并不是消除回调,只是让回调变得更简单,变更可控
async
async 用于去修饰函数(函数声明和函数表达式),放在函数的开始位置,被修饰的函数一定返回一个promise对象
简化promise创建的
async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。
async function helloAsync(){
return "helloAsync";
}
console.log(helloAsync()) // Promise {<resolved>: "helloAsync"}
await 等待
await关键字必须出现在async函数中
async 函数执行时,如果遇到 await 就会先暂停执行 ,等到触发的异步操作完成后,恢复 async 函数的执行并返回解析值
如果await的表达式不是Promise,则会对包装一个promise继续按照规则执行
Iterator 迭代器
1.什么是迭代?
从一个数据集合中按照一定的顺序,不断的取出数据的过程
2.迭代和遍历有什么区别?
迭代强调是依次取出,不能确定取出的有多少,也不能保证把数据全部取完
3.迭代器
对迭代过程的封装,通常为对象,不同的语言中,表现出来的迭代形式不一样
4.迭代模式
一种设计模式,用于同一迭代的过程,并且规范迭代器的规格
迭代器有得到下一个数据的能力 判断是否有后续数据的能力
const Iterator = {
next(){ //用于得到下一个数据
return {
//value : xxx 数据
//done : xxx 判断是否有后续数据,一般为boolean
}
}
通过 next 方法进行向下迭代指向下一个位置, next 方法会返回当前位置的对象,对象包含了 value 和 done 两个属性, value 是当前属性的值, done 用于判断是否遍历结束
当 done 为 true 时则遍历结束
可以直接使用Symbol.iterator创建
const items = ["zero", "one", "two"];
const it = items[Symbol.iterator]();
可迭代的数据结构:
Array
String
Map
Set
Dom元素(正在进行中)
for of 循环就是专门遍历可迭代的对象的,不是可迭代的对象不能使用forof遍历
生成器 generator
生成器就是通过构造函数Generator创建出来的对象,生成器既是一个迭代器,同时又是一个可迭代的对象
Generator 有两个区分于普通函数的部分:
一是在 function 后面,函数名之前有个 * ;
函数内部有 yield 表达式。
其中 * 用来表示函数为 Generator 函数,yield 用来定义函数内部的状态。
function* func(){
console.log("one");
yield '1';
console.log("two");
yield '2';
console.log("three");
return '3';
}
执行机制
调用 Generator 函数和调用普通函数一样,在函数名后面加上()即可,但是 Generator 函数不会像普通函数一样立即执行,而是返回一个指向内部状态对象的指针,所以要调用遍历器对象Iterator 的 next 方法,指针就会从函数头部或者上一次停下来的地方开始执行。
在生成器函数内部去调用别的生成器函数,一定要加上*
函数返回的遍历器对象的方法
next 方法
一般情况下,next 方法不传入参数的时候,yield 表达式的返回值是 undefined 。当 next 传入参数的时候,该参数会作为上一步yield的返回值。
除了使用 next ,还可以使用 for… of 循环遍历 Generator 函数生产的 Iterator 对象。
return 方法
调用以后,可以提前结束生成器函数,整个的迭代过程提前结束
return 方法返回给定值,并结束遍历 Generator 函数。
return 方法提供参数时,返回该参数;不提供参数时,返回 undefined 。
throw 方法
throw 可以在生成器产生一个错误,抛出到对应的行