Skip to content

遍历比较

不可枚举属性包含原型链备注
for...in✔️Symbol 属性不能被遍历
Object.keys()
Reflect.ownKeys✔️等同于
Object.getOwnPropertyNames(target)
.concat(Object.getOwnPropertySymbols(target))

数据类型

7 种基本 string、number、bigint、boolean、null、undefined、symbol 1 种引用 object

深克隆

js
export function deepClone(source, hash = new WeakMap()) {
    if (source.constructor === Date) return new Date(source) // 日期对象直接返回一个新的日期对象
    if (source.constructor === RegExp) return new RegExp(source) // 正则对象直接返回一个新的正则对象
    if (hash.has(source)) return hash.get(source) // 如果循环引用了就用 weakMap 来解决

    // 遍历传入参数所有键的特性
    const target = Object.create(
        Object.getPrototypeOf(source),
        Object.getOwnPropertyDescriptors(source)
    )

    hash.set(source, target)

    for (const key in Reflect.ownKeys(source)) {
        const value = source[key]
        target[key] = value !== null && typeof value === 'object' ? deepClone(value) : value
    }
    return target
}

实现 Call

javascript
Function.prototype.myCall = function (context, ...args) {
    // 如果没有传递上下文对象,则使用全局对象(浏览器环境下为 window)
    context = context || globalThis

    // 将当前函数作为上下文对象的一个属性
    const uniqueKey = Symbol('uniqueKey')
    context[uniqueKey] = this

    // 调用函数,并传递参数
    const result = context[uniqueKey](...args)

    // 删除临时属性
    delete context[uniqueKey]

    return result
}

实现 new 关键字

javascript
function myNew(constructor, ...args) {
    // 创建一个新对象,并将其原型指向构造函数的原型
    const obj = Object.create(constructor.prototype)

    // 调用构造函数,将新对象绑定到构造函数的上下文中
    const result = constructor.apply(obj, args)

    // 如果构造函数返回的是一个对象,则返回该对象;否则返回新创建的对象
    return typeof result === 'object' ? result : obj
}

实现观察者模式

javascript
class Subject {
    constructor() {
        this.observers = []
    }

    addObserver(observer) {
        this.observers.push(observer)
    }

    removeObserver(observer) {
        this.observers = this.observers.filter((obs) => obs !== observer)
    }

    notify(data) {
        this.observers.forEach((observer) => observer.update(data))
    }
}

class Observer {
    constructor(name) {
        this.name = name
    }

    update(data) {
        console.log(`${this.name} 收到更新,数据为:`, data)
    }
}

// 示例用法
const subject = new Subject()

const observer1 = new Observer('观察者1')
const observer2 = new Observer('观察者2')

subject.addObserver(observer1)
subject.addObserver(observer2)

subject.notify('新数据更新了') // 观察者1 收到更新,数据为: 新数据更新了
// 观察者2 收到更新,数据为: 新数据更新了

subject.removeObserver(observer1)

subject.notify('又有新数据更新了') // 只有观察者2会收到更新

实现发布订阅模式

javascript
class Publisher {
    constructor() {
        this.subscribers = []
    }

    subscribe(subscriber) {
        this.subscribers.push(subscriber)
    }

    unsubscribe(subscriber) {
        this.subscribers = this.subscribers.filter((sub) => sub !== subscriber)
    }

    publish(eventData) {
        this.subscribers.forEach((subscriber) => subscriber.notify(eventData))
    }
}

class Subscriber {
    constructor(name) {
        this.name = name
    }

    notify(eventData) {
        console.log(`${this.name} 收到通知,事件数据为:`, eventData)
    }
}

// 示例用法
const publisher = new Publisher()

const subscriber1 = new Subscriber('订阅者1')
const subscriber2 = new Subscriber('订阅者2')

publisher.subscribe(subscriber1)
publisher.subscribe(subscriber2)

publisher.publish('新事件发生了') // 订阅者1 收到通知,事件数据为: 新事件发生了
// 订阅者2 收到通知,事件数据为: 新事件发生了

publisher.unsubscribe(subscriber1)

publisher.publish('又有新事件发生了') // 只有订阅者2会收到通知

简易版 Promise

javascript
class MyPromise {
    constructor(executor) {
        this.status = 'pending'
        this.value = undefined
        this.onResolveCallbacks = []
        this.onRejectCallbacks = []

        const resolve = (value) => {
            if (this.status === 'pending') {
                this.status = 'fulfilled'
                this.value = value
                this.onResolveCallbacks.forEach((callback) => callback(this.value))
            }
        }

        const reject = (reason) => {
            if (this.status === 'pending') {
                this.status = 'rejected'
                this.value = reason
                this.onRejectCallbacks.forEach((callback) => callback(this.value))
            }
        }

        try {
            executor(resolve, reject)
        } catch (error) {
            reject(error)
        }
    }

    then(onFulfilled, onRejected) {
        if (this.status === 'fulfilled') {
            onFulfilled(this.value)
        } else if (this.status === 'rejected') {
            onRejected(this.value)
        } else {
            this.onResolveCallbacks.push(onFulfilled)
            this.onRejectCallbacks.push(onRejected)
        }
    }
}

// 示例用法
const promise = new MyPromise((resolve, reject) => {
    // 异步操作,比如请求数据
    setTimeout(() => {
        resolve('成功')
        // 或者 reject('失败');
    }, 1000)
})

promise.then(
    (value) => {
        console.log('成功:', value)
    },
    (reason) => {
        console.log('失败:', reason)
    }
)

函数式编程

函数式编程是一种"编程范式"(programming paradigm),一种编写程序的方法论

主要的编程范式有三种:命令式编程,声明式编程和函数式编程

相比命令式编程,函数式编程更加强调程序执行的结果而非执行的过程,倡导利用若干简单的执行单元让计算结果不断渐进,逐层推导复杂的运算,而非设计一个复杂的执行过程

javascript
// 命令式编程
const array = [0, 1, 2, 3]
for (let i = 0; i < array.length; i++) {
    array[i] = array[i] ** 2
}

// 函数式方式
;[0, 1, 2, 3].map((num) => num ** 2)