likes
comments
collection
share

[javascript核心-19] 前端常见手写代码实现🦅

作者站长头像
站长
· 阅读数 49

本文github地址:JavaScript_Everything 大前端知识体系与面试宝典,从前端到后端,全栈工程师,成为六边形战士


柯里化函数

如何实现一个通用的柯里化函数?

  1. 需要接收一个需要柯里化的函数
  2. 需要存放每一次函数调用的参数
  3. 对参数进行判断:如果参数数目不够原函数的参数数目,不调用原函数,返回新的函数继续接收下一个参数;反之则调用函数

作用:

  1. 参数复用,逻辑复用
  2. 延时计算,延时执行
function add(num1,num2, num3, num4, num5){
    return num1+num2+ num3+ num4+ num5
}

function curry(fn){
    let self = this
    return function curried(...args){
        if(args.length >= fn.length){
            return fn.apply(self, args)
        }else{
            return function(...otherArgs){
                return curried.apply(self, [...args, ...otherArgs])
            }
        }
    }
}

let newAdd = curry(add)
console.log(newAdd(20 ,30,40,50,60))
console.log(newAdd(20)(30,40,50,60))
console.log(newAdd(20)(30,40)(50,60))
console.log(newAdd(20,30,40)(50,60))

函数组合

利用数组的reduce方法,将多个函数进行组合

function add(num1){
    return num1+1
}

function double(num1){
    return num1 * 2
}

function compose(...fns){
    return function(arg){
        return fns.reduce((prev, fn)=>{
                return fn(prev)
            },arg)
    }
}


let newFn = compose(double,add)
console.log(newFn(10))

考虑一些优化的情况:

  1. 如果给组合函数参数列表传入的函数个数为 0,则直接返回调用时的值
  2. 如果组合函数参数列表只接收到了一个函数,则直接执行该函数,不必进行reduce处理
function add(num1){
    return num1+1
}

function double(num1){
    return num1 * 2
}

function compose(...fns){
    if(fns.length === 0) return arg => arg
    if(fns.length === 1) return fns[0]
    return function(arg){
        return fns.reduce((prev, fn)=>{
                return fn(prev)
            },arg)
    }
}


let newFn = compose(double,add)
console.log(newFn(10)) // 21

let newFn2 = compose()
console.log(newFn2(10)) // 10

let newFn3 = compose(double)
console.log(newFn3(10)) // 20

还可以写的更简洁一些:

function compose(...fns){
    if(fns.length === 0) return arg => arg
    if(fns.length === 1) return fns[0]
    return fns.reduce((result, fn) => (...args) => result(fn(...args)))
}

实现new

  1. 要实例化出一个对象
  2. 实例化出的对象内部的this应该指向实例对象
  3. 应该将实例化对象的隐式原型指向构造函数的原型对象
  4. 构造函数如果有返回值,那构造函数的返回值,就是实例化对象的返回值
  5. 如果构造函数无返回值,则返回空对象
const ObjectFactory = (...args) => {
    // 1.初始化对象
    const obj = {}
    // 2.获取到构造函数
    const constructor = [].shift.call(args)
    // 3.指定原型
    obj.__proto__ = constructor.prototype
    // 4.将构造函数内部的this指向实例对象,并执行构造函数
    const res = constructor.apply(obj, args)
    // 5.保证返回的是对象,如果构造函数无返回值则返回空对象
    return typeof res === 'object' ? res : obj
 }

function Person(name,age){
    this.name = name;
    this.age = age;
    return {
        name: this.name,
        age: this.age,
    }
}

function Person2(name,age){
    this.name = name;
    this.age = age;
}

const obj = ObjectFactory(Person, 'flten', 24)
console.log(obj) // { name: 'flten', age: 24 }

const obj2 = ObjectFactory(Person2, 'flten', 24)
console.log(obj2) // Person2 { name: 'flten', age: 24 }

实现instanceof

instanceof的作用:检测某构造函数的原型对象是否出现在实例对象的原型链上

function Person(name,age){
    this.name = name;
    this.age = age;
}

const obj = new Person()
console.log(obj instanceof Person) // true

实现的关键点:

  1. 获取实例对象的隐式原型
  2. 获取构造函数的原型对象
  3. 通过while循环不断向上查找实例对象的原型链
  4. 对比是否和构造函数的原型对象相同
  5. 如果直到原型链为null,则返回false
  6. 如果出现相同的情况,返回true

实现 instanceof

/**
 * 
 * @param {*} Obj 要检测的对象
 * @param {*} Constructor 目标构造函数
 * @returns boolean 
 */
function instanceOf(Obj, Constructor){
    let   ObjProto = Obj.__proto__
    const ConstructorPrototype = Constructor.prototype
    while(true){
        if(Object.is(ObjProto, null)){
            return false
        }else if(Object.is(ObjProto, ConstructorPrototype)){
            return true
        }
        ObjProto = ObjProto.__proto__
    }
}

function Person(name,age){
    this.name = name;
    this.age = age;
}

const p = new Person()
console.log(instanceOf(p, Person)) // true
console.log(instanceOf(p, Object)) // true
console.log(instanceOf('a', Person)) // false

本文github地址:JavaScript_Everything 大前端知识体系与面试宝典,从前端到后端,全栈工程师,成为六边形战士

转载自:https://juejin.cn/post/7249646017864302647
评论
请登录