Skip to content

import { CodeSandbox } from '@/components/CodeSandbox'

手写题

题目 1:防抖和节流实现

总结:

题目 2:new

总结:

  • 先创建一个空对象,对象的隐式原型指向构造函数的显示原型,用 Object.create 实现更好
  • 然后执行构造函数,将构造函数的 this 指向这个空对象,拿到执行结果
  • 最后返回这个空对象,如果构造函数返回的是一个对象,则返回这个对象,否则返回这个空对象

Object.create(Fn.prototype) 和 const obj = {} {}.proto = Fn.prototype 其实没有什么大区别,也就是 Object.create 更遵循 ES6 写法规范,两者输出是是一样的

题目 3:instanceof

总结:

  • 核心逻辑是左边的 proto 上一直查找有没有等于右边的 prototype,有就返回 true,没有就返回 false
  • while 循环,直到 proto 为 null 为止,因为原型链的尽头是 null,退出条件是找到了则返回 true,没找到则在循环外返回 false
  • 在循环中 proto = Object.getPrototypeOf(proto) 一直往上找

题目 4:拍平数组

总结:

题目 5:深拷贝

总结:

题目 6:控制请求并发

总结:

  • 递归实现
  • 先根据 max 创建 max 个请求,
  • 然后定义 runNext 函数
  • runNext 核心是两个计数变量,一个记录当前队列的索引 index,一个记录正在执行的请求数 running
  • 退出条件是 index >= arr.length 或者 running >= max
  • index++ 和 新建一个 const currentIndex = index++ 拿到当前任务的索引来执行
  • 最后在 finally 中递归调用 runNext 函数,这时候 running--,实现并发控制

对于 index++ 和 ++index 的区别:

js
let index = 0
const result = index++
console.log(result) // 输出: 0 (返回自增前的值)
console.log(index) // 输出: 1 (变量已自增)

let index = 0
const result = ++index
console.log(result) // 输出: 1 (返回自增后的值)
console.log(index) // 输出: 1 (变量已自增)
let index = 0
const result = index++
console.log(result) // 输出: 0 (返回自增前的值)
console.log(index) // 输出: 1 (变量已自增)

let index = 0
const result = ++index
console.log(result) // 输出: 1 (返回自增后的值)
console.log(index) // 输出: 1 (变量已自增)

题目 7:数组转树

总结:

题目 8:大文件上传

题目 9:Call

js
Function.prototype.myCall = function (context, ...args) {
  context = context || window
  const fnKey = Symbol()
  context[fnKey] = this
  const res = context[fnKey](...args) // 相当于谁调用,this就指向谁
  delete context[fnKey]
  return res
}

// 测试示例
function greet(greeting, other) {
  return `${greeting}, ${this.name}${other}`
}

const person = { name: 'Alice' }
greet.myCall(person, 'Hello', '!') // 输出: Hello, Alice!
Function.prototype.myCall = function (context, ...args) {
  context = context || window
  const fnKey = Symbol()
  context[fnKey] = this
  const res = context[fnKey](...args) // 相当于谁调用,this就指向谁
  delete context[fnKey]
  return res
}

// 测试示例
function greet(greeting, other) {
  return `${greeting}, ${this.name}${other}`
}

const person = { name: 'Alice' }
greet.myCall(person, 'Hello', '!') // 输出: Hello, Alice!

题目 10:Apply

js
Function.prototype.myApply = function (context, argsArray) {
  context = context || window
  const fnKey = Symbol()
  context[fnKey] = this
  const args = Array.isArray(argsArray) ? argsArray : []
  const res = context[fnKey](...args) // 相当于谁调用,this就指向谁
  delete context[fnKey]
  return res
}

// 测试示例
function greet(greeting, other) {
  return `${greeting}, ${this.name}${other}`
}

const person = { name: 'Alice' }
greet.myApply(person, ['Hello', '!']) // 输出: Hello, Alice!
Function.prototype.myApply = function (context, argsArray) {
  context = context || window
  const fnKey = Symbol()
  context[fnKey] = this
  const args = Array.isArray(argsArray) ? argsArray : []
  const res = context[fnKey](...args) // 相当于谁调用,this就指向谁
  delete context[fnKey]
  return res
}

// 测试示例
function greet(greeting, other) {
  return `${greeting}, ${this.name}${other}`
}

const person = { name: 'Alice' }
greet.myApply(person, ['Hello', '!']) // 输出: Hello, Alice!