• 手写函数


    1. call

    Function.prototype.myCall = function(context) {
      if (typeof this !== 'function') {
        throw new TypeError('Error')
      }
      context = context || window
      context.fn = this
      const args = [...arguments].slice(1)
      const result = context.fn(...args)
      delete context.fn
      return result
    }
    
    • this 被调用的函数
    • 首先 context 为可选参数,如果不传的话默认上下文为 window
    • 接下来给 context 创建一个 fn 属性,并将值设置为需要调用的函数
    • 因为 call 可以传入多个参数作为调用函数的参数,所以需要将参数剥离出来
    • 然后调用函数并将对象上的函数删除

    2. bind

    Function.prototype.myApply = function(context) {
      if (typeof this !== 'function') {
        throw new TypeError('Error')
      }
      context = context || window
      context.fn = this
      let result
      // 处理参数和 call 有区别
      if (arguments[1]) {
        result = context.fn(...arguments[1])
      } else {
        result = context.fn()
      }
      delete context.fn
      return result
    }
    

    与call的区别在于参数

    3. bind

    Function.prototype.myBind = function (context) {
      if (typeof this !== 'function') {
        throw new TypeError('Error')
      }
      const _this = this
      const args = [...arguments].slice(1)
      // 返回一个函数
      return function F() {
        // 因为返回了一个函数,我们可以 new F(),所以需要判断
        if (this instanceof F) {
          return new _this(...args, ...arguments)
        }
        return _this.apply(context, args.concat(...arguments))
      }
    }
    
    • 前几步和之前的实现差不多,就不赘述了
    • bind 返回了一个函数,对于函数来说有两种方式调用,一种是直接调用,一种是通过 new 的方式,我们先来说直接调用的方式
      • 对于直接调用来说,这里选择了 apply 的方式实现,但是对于参数需要注意以下情况:因为 bind 可以实现类似这样的代码 f.bind(obj, 1)(2),所以我们需要将两边的参数拼接起来,于是就有了这样的实现 args.concat(...arguments)
      • 最后来说通过 new 的方式,在之前的章节中我们学习过如何判断 this,对于 new 的情况来说,不会被任何方式改变 this,所以对于这种情况我们需要忽略传入的 this

    4. new

    function create() {
      let obj = {}
      let Con = [].shift.call(arguments)
      obj.__proto__ = Con.prototype
      let result = Con.apply(obj, arguments)
      return result instanceof Object ? result : obj
    }
    

    以下是对实现的分析:

    • 创建一个空对象
    • 获取构造函数
    • 设置空对象的原型
    • 绑定 this 并执行构造函数
    • 确保返回值为对象

    5. instanceof

    内部机制是通过判断对象的原型链中是不是能找到类型的 prototype

    function myInstanceof(left, right) {
      let prototype = right.prototype
      left = left.__proto__
      while (true) {
        if (left === null || left === undefined)
          return false
        if (prototype === left)
          return true
        left = left.__proto__
      }
    }
    

    以下是对实现的分析:

    • 首先获取类型的原型
    • 然后获得对象的原型
    • 然后一直循环判断对象的原型是否等于类型的原型,直到对象原型为 null,因为原型链最终为 null
  • 相关阅读:
    Spring之InstantiationAwareBeanPostProcessor接口介绍
    Spring之BeanPostProcessor(后置处理器)介绍
    JVM中垃圾收集算法总结
    JVM中对象的回收过程
    zookeeper实现动态感知服务器上下线
    Spring事务的传播行为
    java工厂模式
    Spring加载流程源码分析03【refresh】
    Redis客户端操作之Jedis
    微服务设计的四个原则
  • 原文地址:https://www.cnblogs.com/qiqi715/p/13028806.html
Copyright © 2020-2023  润新知