手写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)