手写Promise
1 定义整体结构
class Promise{
/*
Promise 构造函数
executor: 内部同步执行的函数 (resolve,reject) =>{}
*/
constructor(executor){
}
/*
为 promise指定成功/失败的回调函数
函数的返回值是一个新的 promise对象
*/
then(onResolved, onRejected){
}
/*
为 promise 指定失败的回调函数
是 then(null, onRejected) 的语法糖
*/
catch(onRejected){
}
/*
返回一个指定了成功 value 的 promise 对象
*/
Promise.resolve = function (value){
}
/*
返回一个指定了失败 reason 的 promise 对象
*/
static reject(reason){
}
/*
all方法的实现:返回一个promise,只有promises中 所有的promise都成功时,才最终成功,只要有一个失败就直接失败
*/
static all(promises){
}
/*
race方法的实现:一旦某个promise解决或拒绝,返回的promise就为当前的状态,谁先改变状态返回谁
*/
static race(promises){
}
}
2 Promise构造函数的实现
constructor(executor){
//添加属性
this.PromiseState = 'pending';
this.PromiseResult = null;
//声明属性
this.callbacks = [];
//保存实例对象的 this 的值
const self = this;// self _this that
//resolve 函数
function resolve(data){
//判断状态
if(self.PromiseState !== 'pending') return;
//1. 修改对象的状态 (promiseState)
self.PromiseState = 'fulfilled';// resolved
//2. 设置对象结果值 (promiseResult)
self.PromiseResult = data;
//调用成功的回调函数
setTimeout(() => {
self.callbacks.forEach(item => {
item.onResolved(data);
});
});
}
//reject 函数
function reject(data){
//判断状态
if(self.PromiseState !== 'pending') return;
//1. 修改对象的状态 (promiseState)
self.PromiseState = 'rejected';//
//2. 设置对象结果值 (promiseResult)
self.PromiseResult = data;
//执行失败的回调
setTimeout(() => {
self.callbacks.forEach(item => {
item.onRejected(data);
});
});
}
try{
//同步调用『执行器函数』
executor(resolve, reject);
}catch(e){
//修改 promise 对象状态为『失败』
reject(e);
}
}
3 promise.then()/catch()的实现
//then 方法封装
then(onResolved,onRejected){
const self = this;
//判断回调函数参数
if(typeof onRejected !== 'function'){
onRejected = reason => {
throw reason;
}
}
if(typeof onResolved !== 'function'){
onResolved = value => value;
//value => { return value};
}
return new Promise((resolve, reject) => {
//封装函数
function callback(type){
try{
//获取回调函数的执行结果
let result = type(self.PromiseResult);
//判断
if(result instanceof Promise){
//如果是 Promise 类型的对象
result.then(v => {
resolve(v);
}, r=>{
reject(r);
})
}else{
//结果的对象状态为『成功』
resolve(result);
}
}catch(e){
reject(e);
}
}
//调用回调函数 PromiseState
if(this.PromiseState === 'fulfilled'){
setTimeout(() => {
callback(onResolved);
});
}
if(this.PromiseState === 'rejected'){
setTimeout(() => {
callback(onRejected);
});
}
//判断 pending 状态
if(this.PromiseState === 'pending'){
//保存回调函数
this.callbacks.push({
onResolved: function(){
callback(onResolved);
},
onRejected: function(){
callback(onRejected);
}
});
}
})
}
//catch 方法
catch(onRejected){
return this.then(undefined, onRejected);
}
4 Promise.resolve()/reject()的实现
//添加 resolve 方法
static resolve(value){
//返回promise对象
return new Promise((resolve, reject) => {
if(value instanceof Promise){
value.then(v=>{
resolve(v);
}, r=>{
reject(r);
})
}else{
//状态设置为成功
resolve(value);
}
});
}
//添加 reject 方法
static reject(reason){
return new Promise((resolve, reject)=>{
reject(reason);
});
}
5 Promise.all/race()的实现
//添加 all 方法
static all(promises){
//返回结果为promise对象
return new Promise((resolve, reject) => {
//声明变量
let count = 0;
let arr = [];
//遍历
for(let i=0;i<promises.length;i++){
//
promises[i].then(v => {
//得知对象的状态是成功
//每个promise对象 都成功
count++;
//将当前promise对象成功的结果 存入到数组中
arr[i] = v;
//判断
if(count === promises.length){
//修改状态
resolve(arr);
}
}, r => {
reject(r);
});
}
});
}
//添加 race 方法
static race (promises){
return new Promise((resolve, reject) => {
for(let i=0;i<promises.length;i++){
promises[i].then(v => {
//修改返回对象的状态为 『成功』
resolve(v);
},r=>{
//修改返回对象的状态为 『失败』
reject(r);
})
}
});
}
6 class类封装
class类封装:在js
的类中,可分为三种方法,constructor构造方法、静态方法与普通方法
。
「constructor构造方法」
1.概念
类的作用在于构建对象,而constructor构造方法就是用于构建对象实例。
2.使用方法
在使用new关键字生成对象时,constructor方法会被执行,最终return的结果就是生成的对象实例。
当一个类没有constructor方法时会自动生成一个空的constructor方法,返回结果为空。
用new关键字实例化对象时传入的参数会做为constructor构造函数的参数传入。
class Point {
constructor(name) {
console.log('Instantiate objects:'+ name);
}
}
new Point('testObj');
//Instantiate objects:testObj
「普通方法」
1.概念
class类的普通方法可以看作是构造函数的另一种写法,相当于在类的prototype属性上上边定义方法。
2.使用方法
(1).该类实例化的对象上使用此方法
class Point {
toString() {
// ...
}
}
let obj = new Point();
obj.toString();
(2).直接通过该类的prototype调用此方法
class Point {
toString() {
// ...
}
}
Point.prototype.toString();
(3).通过子类的__proto__
调用
class Foo {
commonMethod() {
return 'hello';
}
}
class Bar extends Foo {
}
Bar.__proto__.prototype.commonMethod();
「静态方法」
1.概念
类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法**不会被实例继承
,而是直接通过类来调用(通过类调用指在该类之外调用**),这就称为“静态方法”。
2.使用方法
静态方法只能在当前类上调用,不能被该类的实例对象调用。父类的静态方法可以被子类继承。
因此静态方法被调用的方式一共有三种(三种调用方式都在下面一段代码中使用到了,请耐心阅读):
- 父类直接调用
- 子类继承父类后调用
- 子类通过super对象调用
class Foo {
static classMethod() {
return 'hello';
}
}
Foo.classMethod(); //hello
class Bar extends Foo {
}
class Cla extends Foo {
return super.classMethod(); //hello
}
Bar.classMethod(); //hello
对比 | 静态方法 | 普通方法 | 构造方法 |
---|---|---|---|
关键字 | static | 无 | constructor |
使用场景 | 声明一个仅供当前类或当前类的子类使用的方法 | 创建实例化对象可直接调用的方法 | 在用new关键字通过此类实例化对象时执行的方法 |
使用对象 | 当前类或当前类的子类 | 通过该类或该类的子类实例化生成的对象 | 该类自身 |
调用方法 | 1.父类直接调用 2.子类继承父类后调用 3.子类通过super对象调用 | 1.通过该类及该类的子类实例生成的对象调用 2.该类通过prototype调用 3.该类的子类通过__proto__隐式原型链调用 | 1.该类实例化对象时调用 2.该类的子类使用super关键字调用 |
注:在class类中,它的静态属性与普通属性允许重名。但是不建议重名,这里就不给出demo了
示例demo
class Person{
constructor() {
// 添加到 this 的所有内容都会存在于不同的实例上
this.locate = () => console.log('instance',this);
}
// 定义在类的原型对象上
locate(){
console.log('prototype', this);
}
// 定义在类本身上
static locate(){
console.log('class',this);
}
}
let p = new Person();
p.locate(); // instance, Person()
Person.prototype.locate(); // prototype. {constructor: ... }
Person.locate(); // class, class Person { }