1. 手写 Object.create
Object.create 方法创建一个新对象,使用现有的对象来提供新创建的对象的 __proto__。
function create(obj) {
function F() {}
F.prototype = obj
return new F()
}
核心原理:通过一个中间构造函数,将其原型指向传入的对象,然后返回这个构造函数的实例。
2. 手写 instanceof 方法
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
function myInstanceof(left, right) {
let proto = Object.getPrototypeOf(left)
let prototype = right.prototype
while (true) {
if (!proto) return false
if (proto === prototype) return true
proto = Object.getPrototypeOf(proto)
}
}
实现要点:沿着原型链向上查找,直到找到匹配的原型或到达链的末端。
3. 手写 new 操作符
new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。
function myNew(constructor, ...args) {
// 1. 创建一个新对象,并将其原型指向构造函数的prototype
const obj = Object.create(constructor.prototype)
// 2. 执行构造函数,绑定this到新对象
const result = constructor.apply(obj, args)
// 3. 如果构造函数返回了一个对象,则返回该对象
return result instanceof Object ? result : obj
}
关键步骤:原型连接、构造函数执行、返回值处理。
4. 手写 Promise
Promise 是异步编程的一种解决方案,比传统的回调函数更加合理和强大。
class MyPromise {
constructor(executor) {
this.state = 'pending'
this.value = undefined
this.reason = undefined
this.onFulfilledCallbacks = []
this.onRejectedCallbacks = []
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled'
this.value = value
this.onFulfilledCallbacks.forEach(fn => fn())
}
}
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected'
this.reason = reason
this.onRejectedCallbacks.forEach(fn => fn())
}
}
try {
executor(resolve, reject)
} catch (err) {
reject(err)
}
}
then(onFulfilled, onRejected) {
// then方法实现见下一节
}
}
5. 手写 Promise.then
then 方法返回一个 Promise,它最多需要有两个参数:Promise 的成功和失败情况的回调函数。
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
const promise2 = new MyPromise((resolve, reject) => {
if (this.state === 'fulfilled') {
setTimeout(() => {
try {
const x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
} else if (this.state === 'rejected') {
setTimeout(() => {
try {
const x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
} else if (this.state === 'pending') {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
}
})
return promise2
}
function resolvePromise(promise2, x, resolve, reject) {
if (x === promise2) {
return reject(new TypeError('Chaining cycle detected for promise'))
}
if (x instanceof MyPromise) {
x.then(resolve, reject)
} else {
resolve(x)
}
}
6. 手写 Promise.all
Promise.all 方法接收一个promise的iterable类型输入,并返回一个Promise实例。
function promiseAll(promises) {
return new Promise((resolve, reject) => {
let results = []
let count = 0
promises.forEach((promise, index) => {
Promise.resolve(promise).then(res => {
results[index] = res
count++
if (count === promises.length) {
resolve(results)
}
}).catch(reject)
})
})
}
特点:全部成功时返回结果数组,有一个失败立即拒绝。
7. 手写 Promise.race
Promise.race 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。
function promiseRace(promises) {
return new Promise((resolve, reject) => {
promises.forEach(promise => {
Promise.resolve(promise).then(resolve).catch(reject)
})
})
}
特点:竞速,第一个 settled 的 promise 决定结果。
8. 手写防抖函数
防抖:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
function debounce(fn, delay) {
let timer = null
return function (...args) {
clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this, args)
}, delay)
}
}
应用场景:搜索框输入、窗口大小调整。