手写instanceof

function myInstanceof(source, ctor) {
  /** 判断非引用类型 */
  if (!["function", "object"].includes(typeof source) || source === null) return false
 
  /** 查找原型链 */
  let proto = Object.getPrototypeOf(source)
  while (true) {
    if (proto === null) return false
    if (proto === ctor.prototype) return true
    proto = Object.getPrototypeOf(proto)
  }
}

手写call

Function.prototype.myCall = function (ctx, ...args) {
  // 参数归一化
  ctx = ctx === undefined || ctx === null ? globalThis : Object(ctx)
 
  // 拿到要执行的函数
  const fn = this
 
  // 绑定函数到ctx,(优化:不能被遍历到)
  const key = Symbol("function_call")
  Object.defineProperty(ctx, key, {
    value: fn,
    enumerable: false,
  })
 
  // 执行函数并返回对应的结果
  const result = ctx[key](...args)
  delete ctx[key]
  return result
}
 
function test(a, b) {
  console.log(this, a, b, this.name)
  return a + b
}
 
console.log(test.myCall({ name: "tttt" }, 1, 3))

手写bind

Function.prototype.myBind = function (ctx, ...args) {
  // 要执行的函数
  const fn = this
 
  return function A(...rest) {
    // 如果是 new 调用的,保留new的行为
    if (Object.getPrototypeOf(this) === A.prototype) {
      // 或者 this instanceof A
      return new fn(...args, ...rest)
    }
 
    // 执行函数并返回结果
    return fn.apply(ctx, [...args, ...rest])
  }
}
 
function test(a, b, c, d) {
  console.log(this, a, b, c, d)
  return a + b
}
 
const newFn = test.myBind({ name: "aa" }, 1, 2)
console.log(newFn(3, 4))
console.log(new newFn(3, 4))

手写深拷贝

function deepClone(obj) {
  const objectMap = new Map()
  const _deepClone = value => {
    const type = typeof value
 
    // 如果是 值类型 或 null,则直接return
    if (type !== "object" || value === null) {
      return value
    }
 
    if (objectMap.has(value)) {
      return objectMap.get(value)
    }
 
    const result = Array.isArray(value) ? [] : []
    objectMap.set(value, result)
 
    for (const key in value) {
      result[key] = _deepClone(value[key])
    }
    return result
  }
 
  return _deepClone(obj)
}

函数柯理化

const curry = (fn) => 
  curried = (...args) => 
    args.length >= fn.length 
      ? fn(...args) 
      : (...nextArgs) => curried(...args, ...nextArgs);
 
// 结合 compose 或 pipe 实现复杂逻辑
// 组合多个函数
const compose = (...fns) => x => fns.reduceRight((v, f) => f(v), x);
 
// 柯里化处理数据流
const toUpperCase = str => str.toUpperCase();
const exclaim = str => str + '!';
const emphasize = compose(curry(exclaim), curry(toUpperCase));

手写memoize

function memoize(func, resolver) {
  const memoized = (...args) => {
    const key = resolver ? resolver(...args) : args[0]
    if (memoized.cache.has(key)) {
      return memoized.cache.get(key)
    }
 
    const result = func.apply(this, args)
    memoized.cache.set(key, result)
    return result
  }
 
  memoized.cache = new Map()
 
  return memoized
}
 
const obj = { a: 1, b: 2 }
const other = { c: 3, d: 4 }
 
const values = memoize(
  obj => Object.values(obj),
  // () => ({})
)
 
console.log(values(obj))
console.log(values(other))
 
obj.a = 55
console.log(values(obj))
 

实现函数重载

function addMethod(obj, name, fn) {
  const old = obj[name]
 
  obj[name] = function (...args) {
    if (args.length === fn.length) {
      return fn.apply(this, args)
    } else if (typeof old === "function") {
      return old.apply(this, args)
    }
  }
}
 
const obj = {}
addMethod(obj, "query", () => {
  console.log("查询所有")
})
addMethod(obj, "query", name => {
  console.log("通过name查找")
})
addMethod(obj, "query", (name, age) => {
  console.log("通过name+age查找")
})
 
obj.query()
obj.query('aaa')
obj.query('aaa', 12)