手撕面试题之 new操作符、instanceof操作符、函数柯里化、函数组合

279 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

手撕面试题之 new操作符、instanceof操作符、函数柯里化、函数组合

new操作符

    const _new = function _new(Ctor,...params){
      // 格式校验:函数 & 有原型对象 & 不是Symbol/BigInt
      if(typeof Ctor !== 'function') throw new TypeError(`${Ctor} is not a constructor`)
      let name = Ctor.name,
          proto = Ctor.prototype
      if(/^(Symbol|BigInt)$/i.test(name) || !proto) throw new TypeError(`${name} is not a constructor`)
      // 创建一个当前类的实例对象
      let obj = Object.create(Ctor.prototype)

      // 把构造函数像普通函数一样执行,但是this需要指向创建的实例对象
      let result = Ctor.call(obj,...params)

      // 看函数的返回值,如果没有写返回值,或者返回的是原始值,我们默认返回实列对象;如果返回的是对象,则以自己返回的为主
      if(result !== null && /^(object|function)$/i.test(typeof result)) return result
      return obj
    }

instanceof操作符

    const instance_of = function instance_of(obj, Ctor) {
      if(Ctor == null) throw new TypeError('Right-hand side of instanceof is not a object')
      if (typeof Ctor !== 'function') throw new TypeError('Right-hand side of instanceof is not callable')
      if (!Ctor.prototype) throw new Error('Function has non-object prototype undefined in instanceof check')

      if(obj == null || !/^(object|function)$/.test(typeof obj)) return false

      if(typeof Ctor[Symbol.hasInstance] === 'function') return Ctor[Symbol.hasInstance](obj)

      let proto = Object.getPrototypeOf(obj)
      while (proto) {
        if(proto === Ctor.prototype) return true
        proto = Object.getPrototypeOf(proto)
      }
      return false
    }

函数柯里化

预先存储(预处理),利用闭包的"保存机制",我们把一些值事先存储起来,供其下级上下文中后期使用.

    const curry = function curry(func){
      if(typeof func !== 'function') throw new TypeError(`${func} is not a function`)

      return function curried(...params) {
        if (params.length < func.length) {
          return function(...args){
            return curried(...params.concat(args))
          }
        }
        return func(...params)
      }
    }

函数组合

如果一个函数要经过多个函数处理才能得到最终值(类似这样h(g(f(x)))),这个时候可以把中间 过程的函数合并成一个函数,函数就像是数据的管道,函数组合就是把这些管道连接起来,让数据穿过多个管道形成最终结果,函数组合默认是从右到左执行。

    const compose = function compose(...funcs){
      let len = funcs.length
      if(len === 0) x => x
      if(len === 1) return funcs[0]
      return function operate(x){
        return funcs.reduceRight((memo, func) => {
          return func(memo)
        }, x)
      }
    }