前端核心代码

155 阅读2分钟

1、call的实现

   Function.prototype.myCall = function(context,...args){
    var context = context || window;
    
    //这里的this指的是调用 mycall 的函数
    // 并为要指向的对象添加一个 fn 方法
    context.fn = this;
    
    // 并立即调用
    var result = context.fn(...args);
    
    //删除该方法,不然会对传入对象造成污染(添加该方法)
    delete context.fn;
   
    return result;
}

2、apply的实现

  • 前部分与call一样
  • 第二个参数没有用扩展运算符,接收是一个数组
  Function.prototype.myApply = function(context,args){
    var context = context || window;
    
    //这里的this指的是调用 myApply 的函数
    // 并为要指向的对象添加一个 fn 方法
    context.fn = this;
    
    // 并立即调用
    var result = context.fn(...args);
    
    //删除该方法,不然会对传入对象造成污染(添加该方法)
    delete context.fn;
   
    return result;
   
}

3、bind的实现

实现方法:

  • bind 方法不会立即执行,需要返回一个待执行的函数;(闭包)

  • 实现作用域绑定(apply)

  • 参数传递(apply 的数组传参)

  • 当作为构造函数的时候,进行原型继承

Function.prototype.myBind = function (context, ...args) {
    //新建一个变量赋值为this,表示当前函数
    const fn = this
    //判断有没有传参进来,若为空则赋值[]
    args = args ? args : []
    //返回一个newFn函数,在里面调用fn
    return function newFn(...newFnArgs) {
    
        if (this instanceof newFn) {
            返回的函数当构造函数用,可以返回直接的结果
            return new fn(...args, ...newFnArgs)
        }
        
        // 如果不用上面判断,此时返回的值可能字符串,但此时new + 后面的值(字符串)就不能当构造函数
        return fn.apply(context, [...args,...newFnArgs])
    }
}

4、new 的实现

  • 当构造函数最后 return 出来的是一个和 this 无关的对象时,new 命令会直接返回这个新对象,而不是通过 new 执行步骤生成的 this 对象

  • 当构造函数最后返回的不是对象,那么还是会按照 new 的实现步骤,返回新生成的对象

  • 让实例可以访问到私有属性;

  • 让实例可以访问构造函数原型(constructor.prototype)所在原型链上的属性;

  • 构造函数返回的最后结果是引用数据类型。

  function _new(ctor, ...args) {
    if(typeof ctor !== 'function') {
      throw 'ctor must be a function'
    }
    let obj = new Object();
    obj.__proto__ = Object.create(ctor.prototype);
    let res = ctor.apply(obj, [...args]);
    
    let isObject = typeof res === 'object' && res !== null;
    let isFunction = typeof res === 'function';
    return isObject || isFunction ? res : obj;
  }

5、instance of 的实现

   function my_instance(left, right){
     if(left === null || typeof left !== 'object') {
       return false
     }
     // 获取对象的原型,也可以使用 left.__proto__
     let proto = Object.getPrototypeOf(left);
     while(true) {
       if(proto === null) return false;
       // 一般实例对象的原型和构造函数的原型指向同一个地址
       if(proto === right.prototype) return true;
       // 循环找left 的原型,直到找到null 或者 是等于right 的原型
       proto = Object.getPrototypeOf(proto);
     }
   }

6、判断数据类型

   function getType(obj){
     const type = typeof obj;
     if(type !== 'object') {
       return type;
     }
     return Object.prototype.toString.call(obj).replace(/^\[object (\s+)\]$/, '$1');
   }