【前端面试】JavaScript手写代码

1. 实现一个new操作符

 在实现之前,首先分析new操作符做了什么事
复制代码
  • 构建了一个全新的对象: var obj = {}

  • new通过构造函数创建出的实例可以访问到构造函数原型链的属性 : obj.propt = fn.Prototype

  • 改变this的指向,让fn里的this指向新构建的对象,并执行fn函数体: const ret = fn.apply(obj)

  • 判断fn的返回值类型,如果是对象,就返回ret,如果是值类型,就返回obj

    function _new (fn , ...args) {
      var obj = {}
      obj.__proto = fn.prototype
      const ret = fn.apply(obj, args)
      return typeof ret === 'object' ? ret : obj
    }
复制代码

2. 实现深浅copy

 在实现之前,我们要先知道什么是深浅拷贝
复制代码
  • 浅拷贝: 只复制指向某个对象的指针,而不复制对象本身,新旧对象共享一块内存
  • 深拷贝: 复制并创建一个一摸一样的对象,不共享内存,修改新对象,旧对象保持不变
   function shallowCopy(obj) {
      if (typeof obj !== 'object') return
      let newobj = obj instanceof Array ? [] : {}
      for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
          newobj[key] = obj[key]
        }
      }
      return newobj
    }
复制代码
   function deepCopy(obj) {
      if (typeof obj !== 'object') return
      var newobj = obj instanceof Array ? [] : {}
      for (var key in obj) {
        newobj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key]
      }
      return newobj
    }
复制代码

3. instanceof的实现

 在深浅copy里我们使用到了instanceof方法,接下来我们实现一下这个方法,我们已经知道它是用来判断值的类型的了。但是其实上,他的真正作用的用来判断某个对象是不是另一个对象的实例
复制代码
    function _instanceof(left, right) {
      let L = left.__proto__
      let R = right.prototype
      while(true) {
        if (L === null) return false
        if (L === R) return true
        L = L.__proto__
      }
    }
复制代码

4.手写call,apply,bind

三者的不同与用法
复制代码
  • call 接收多个参数,第一个为函数上下文也就是this,后边参数为函数本身的参数
  • apply 接收两个参数,第一个参数为函数上下文this,第二个参数为函数参数只不过是通过一个数组的形式传入的
  • bind 接收多个参数,第一个是bind返回值返回值是一个函数上下文的this,不会立即执行。
    Function.prototype.mycall = function (context, ...args) {
      context = context || window
      const key = Symbol()
      context.key = this
      return context.key(...args)
      delete context.key()
    }
复制代码
    Function.prototype.myapply = function (context, args) {
      context = context || window
      const key = Symbol()
      context.key = this
      return context.key(...args)
      delete context.key()
    } 
复制代码
    Function.prototype.mybind = function (context) {
      context = (typeof context === 'object' ? context : window)
      return (...args) => {
        console.log(args)
        this.call(context, ...args)
      }
    }
复制代码

5. 防抖节流

  • 防抖:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
  • 节流:规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。
    // 防抖
    function debounce (func, delay) {
      var timeout
      return function () {
        clearTimeout(timeout)
        timeout = setTimeout(() => {
          func.apply(this, arguments)
        }, delay)
      }
    }
复制代码
   // 节流
   function throttle(func, delay) {
      var last = 0
      return function() {
        var now = Date.now()
        if (now > last + delay) {
          func.apply(this, arguments)
          last = now
        } else {
          console.log('间隔时间不满足要求')
        }
      }
    }

复制代码

6. 柯里化

  • 柯里化(Currying),又称部分求值(Partial Evaluation),是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。核心思想是把多参数传入的函数拆成单参数(或部分)函数,内部再返回调用下一个单参数(或部分)函数,依次处理剩余的参数
    var curry = function (fn) {
      var args = [].slice.call(arguments, 1)
      return function () {
        var newArgs = args.concat([].slice.call(arguments))
        return fn.apply(this, newArgs)
      }
    }
复制代码

7. 继承

    //原型链+构造函数
    function Parent(value) {
      this.val = value
    }
    Parent.prototype.getValue = function () {
      console.log(this.val)
    }
    function Child(value) {
      Parent.call(this, value)
    }
    Child.prototype = new Parent()
复制代码
    //寄生组合继承
    function Parent(value) {
      this.val = value
    }
    Parent.prototype.getValue = function () {
      console.log(this.val)
    }
    function Child(value) {
      Parent.call(this, value)
    }
    Child.prototype = Object.create(Parent.prototype, {
      constructor: {
        value: Child,
        enumerable: false,
        writable: true,
        configurable: true
      }
    })
复制代码
    //class继承
    class Parent {
      constructor(value) {
        this.val = value
      }
      getValue() {
        console.log(this.val)
      }
    }
    class Child extends Parent {
      constructor(value) {
        super(value)
        this.val = value
      }
    }
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享