手写代码
实现原生 Ajax
js
const ajax = {
get(url, fn) {
const xhr = new XMLHttpRequest()
xhr.open('GET', url, true) // 第三个参数异步与否
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE) {
fn(xhr.responseText)
}
}
xhr.close()
},
post(url, data, fn) {
const xhr = new XMLHttpRequest()
xhr.open('POST', url, true)
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE) {
fn(xhr.responseText)
}
}
xhr.send(data)
},
}
new
的过程
js
function myNew(fn, ...args) {
const obj = {}
obj.__proto__ = fn.prototype
fn.apply(obj, args)
return obj
}
instance
关键字
js
function instanceOf(father, child) {
const fp = father.prototype
var cp = child.__proto__
while (cp) {
if (cp === fp) {
return true
}
cp = cp.__proto__
}
return false
}
实现 Promise
js
class Mypromise {
constructor(fn) {
// 表示状态
this.state = 'pending'
// 表示then注册的成功函数
this.successFun = []
// 表示then注册的失败函数
this.failFun = []
let resolve = val => {
// 保持状态改变不可变(resolve和reject只准触发一种)
if (this.state !== 'pending') return
// 成功触发时机 改变状态 同时执行在then注册的回调事件
this.state = 'success'
// 为了保证then事件先注册(主要是考虑在promise里面写同步代码) promise规范 这里为模拟异步
setTimeout(() => {
// 执行当前事件里面所有的注册函数
this.successFun.forEach(item => item.call(this, val))
})
}
let reject = err => {
if (this.state !== 'pending') return
// 失败触发时机 改变状态 同时执行在then注册的回调事件
this.state = 'fail'
// 为了保证then事件先注册(主要是考虑在promise里面写同步代码) promise规范 这里模拟异步
setTimeout(() => {
this.failFun.forEach(item => item.call(this, err))
})
}
// 调用函数
try {
fn(resolve, reject)
} catch (error) {
reject(error)
}
}
// 实例方法 then
then(resolveCallback, rejectCallback) {
// 判断回调是否是函数
resolveCallback =
typeof resolveCallback !== 'function' ? v => v : resolveCallback
rejectCallback =
typeof rejectCallback !== 'function'
? err => {
throw err
}
: rejectCallback
// 为了保持链式调用 继续返回promise
return new Mypromise((resolve, reject) => {
// 将回调注册到successFun事件集合里面去
this.successFun.push(val => {
try {
// 执行回调函数
let x = resolveCallback(val)
//(最难的一点)
// 如果回调函数结果是普通值 那么就resolve出去给下一个then链式调用 如果是一个promise对象(代表又是一个异步)
// 那么调用x的then方法 将resolve和reject传进去 等到x内部的异步 执行完毕的时候(状态完成)就会自动执行传入的
// resolve 这样就控制了链式调用的顺序
x instanceof Mypromise ? x.then(resolve, reject) : resolve(x)
} catch (error) {
reject(error)
}
})
this.failFun.push(val => {
try {
// 执行回调函数
let x = rejectCallback(val)
x instanceof Mypromise ? x.then(resolve, reject) : reject(x)
} catch (error) {
reject(error)
}
})
})
}
//静态方法
static all(promiseArr) {
let result = []
//声明一个计数器 每一个promise返回就加一
let count = 0
return new Mypromise((resolve, reject) => {
for (let i = 0; i < promiseArr.length; i++) {
//这里用 Promise.resolve包装一下 防止不是Promise类型传进来
Promise.resolve(promiseArr[i]).then(
res => {
//这里不能直接push数组 因为要控制顺序一一对应(感谢评论区指正)
result[i] = res
count++
//只有全部的promise执行成功之后才resolve出去
if (count === promiseArr.length) {
resolve(result)
}
},
err => {
reject(err)
},
)
}
})
}
//静态方法
static race(promiseArr) {
return new Mypromise((resolve, reject) => {
for (let i = 0; i < promiseArr.length; i++) {
Promise.resolve(promiseArr[i]).then(
res => {
//promise数组只要有任何一个promise 状态变更 就可以返回
resolve(res)
},
err => {
reject(err)
},
)
}
})
}
}