遍历比较
| 不可枚举属性 | 包含原型链 | 备注 | |
|---|---|---|---|
| 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)