我是歌谣 放弃很容易 但是坚持一定很酷 微信公众号关注小歌谣一起学习前后端知识

闲来无事做 不如敲代码

今天讲一下js里面的call

apply和bind和typeof方法

的手动封装

由于最近比较忙

但是有时间

就会记录一下平时学习工作的一些代码用来分享

这边就不直接多说开始我们的直接代码书写表演

如果有什么不清楚的地方

可以自己进行一个观察讨论

这个代码是对js进行的相关语法进行的一个封装

顺便对于vite2.0做了一个简单的一个学习

vite2.0相对于webpack打包工具拥有自己的特点

我是歌谣 放弃很容易 但是坚持一定很酷

const utilsModule = ((Function) => {
  
/**
 

  // context
  Function.prototype.myCall = function (ctx) {
    // ctx => { a: 1, b: 2 }
    // this => test => this => ctx
    // ctx => object
    // ctx.test => test -> this => ctx
    ctx = ctx ? Object(ctx) : window;
    // originFn & test -> 一个内存地址
    ctx.originFn = this; // 引用 

    var args = [];
    
    // 拿到myCall的第二个参数开始到结束的所有参数作为test的实参列表
    for (var i = 1; i < arguments.length; i ++) {
      // args + 字符串 -> args 展开平铺到fn的实参中去
      args.push('arguments[' + i + ']');
    }
    
    // ctx.originFn([arguments[1], arguments[2]]);
    // ctx.originFn(['arguments[1]', 'arguments[2]']);
    // 'ctx.originFn([arguments[1], arguments[2]])'
    var ret = eval('ctx.originFn(' + args + ')')
    delete ctx.orgiinFn;

    return ret;
  }

  Function.prototype.myApply = function (ctx, args) {
    ctx = ctx ? Object(ctx) : window;
    ctx.originFn = this;

    if (typeof args !== 'object' && typeof args !== 'function') {
      throw new TypeError('CreateListFromArrayLike called on non-object');
    }

    if (!args || typeOf(args) !== 'Array') {
      return ctx.originFn();
    }

    var ret = eval('ctx.originFn(' + args + ')');
    delete ctx.originFn;
    return ret;
  }

  Function.prototype.myBind = function (ctx) {
    var originFn = this,
        // bind传递的test的参数
        args = [].slice.call(arguments, 1),
        // 原型传递中介函数
        _tempFn = function () {};

    var newFn = function () {
      // 返回的新函数t的参数列表
      var newArgs = [].slice.call(arguments);
                            // 如果new t, this -> newFn构造出来的,实例化了,this -> newFn的实例 : ctx
      return originFn.apply(this instanceof newFn ? this : ctx, args.concat(newArgs));
    }
    
    // 将test.prototype => 中介函数的原型属性
    _tempFn.prototype = this.prototype;
    // 讲中介函数的实例化对象 => newFn的原型属性
    newFn.prototype = new _tempFn();

    return newFn;
  }

  function typeOf (value) {
    if (value === null) {
      return 'null';
    }

    // ({}).toString.call(value) -> [object Object]

    // var types = {
    //   '[object Object]': 'Object',
    //   '[object Array]': 'Array',
    //   '[object Number]': 'Number',
    //   '[object String]': 'String',
    //   '[object Boolean]': 'Boolean'
    // };

    // if (typeof(value) === 'object') {
    //   var res = ({}).toString.call(value); //[object Object]
    //   var type = types[res]
    // }

    return typeof(value) === 'object' ? {
      '[object Object]': 'Object',
      '[object Array]': 'Array',
      '[object Number]': 'Number',
      '[object String]': 'String',
      '[object Boolean]': 'Boolean'
    }[({}).toString.call(value)] : typeof(value);
  }

  // var test = myNew(Test, 1, 2);

  function myNew () {
    var constructor = [].shift.call(arguments),
        _this = {};
    
    _this.__proto__ = constructor.prototype;
    
    var res = constructor.apply(_this, arguments);
    return typeOf(res) === 'Object' ? res : _this;
  }

  function instanceOf (target, type) {
    type = type.prototype;
    target = target.__proto__;

    while (true) {
      if (target === null) {
        return false;
      }
      
      if (target === type) {
        return true;
      }

      target = target.__proto__;
    }
  }

  return {
    typeOf,
    myNew,
    instanceOf
  }

})(Function);

export default utilsModule;

我是歌谣 放弃很容易 但是坚持一定很酷 一起成为前端大佬 谢谢