new、call、apply、bind的模拟实现

吐槽君 分类:javascript

1. new 的模拟实现

 function newFactory(fn,...arguments) {
   var obj = {};
   obj.__proto__ = fn.prototype;
   const ret = fn.call(obj, ...arguments);
   return typeof ret === 'object' ? ret : obj;
};
 
  1. 创建一个空对象 obj;
  2. 将新创建的空对象的隐式原型指向其构造函数的显示原型。
  3. 使用 call 改变 this 的指向
  4. 如果无返回值或者返回一个非对象值,则将 obj 返回作为新对象;如果返回值是一个新对象的话那么直接直接返回该对象。

验证:

function Person(age, name) {
  this.age = age;
  this.name = name;
  return "new car";
}

var person = newFactory (Person,18, "Tom");
 

2. call 的模拟实现

Function.prototype.callFun = function (context, ...args) {
  var context = context || window;
  context.fn = this;
  const result = context.fn(...args);
  delete context.fn;
  return result;
};
 
  1. 将函数设为对象的属性
  2. 执行该函数
  3. 删除该函数

验证:

const value2 = 2;

const obj2 = {
  value: 1
};

function bar(name, age) {
  console.log(this.value);
  return {
      value: this.value,
      name: name,
      age: age
  };
}

console.log(bar.call(obj2, 'kevin', 18]);
 

3. apply 的模拟实现

apply与call的不同,接收的是数组参数。

Function.prototype.apply = function (context, arr) {
    var context = Object(context) || window;
    context.fn = this;

    var result;
    if (!arr) {
        result = context.fn();
    }
    else {
        result = context.fn(...arr);
    }

    delete context.fn
    return result;
}
 

验证:

const value2 = 2;

const obj2 = {
  value: 1
};

function bar(name, age) {
  console.log(this.value);
  return {
      value: this.value,
      name: name,
      age: age
  };
}

console.log(bar.apply(obj2, ['kevin', 18]));
 

4. bind 的模拟实现

bind返回的是一个函数,而不是执行结果。

Function.prototype.bindFun = function (context,...args) {

    if (typeof this !== "function") {
      throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
    }

    var self = this;

    var fNOP = function () {};

    var fBound = function () {
        var bindArgs = Array.prototype.slice.call(arguments);
        return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
    }

    fNOP.prototype = this.prototype;
    fBound.prototype = new fNOP();
    return fBound;
}
 
bar.bindFun(obj, 'kevin', 18)()
 
  • JavaScript深入之new的模拟实现
  • JavaScript深入之call和apply的模拟实现

原文链接:https://juejin.cn/post/6943434817878884382

回复

我来回复
  • 暂无回复内容