深入理解new关键词,并手写实现
分类: 前端开发
2024-06-23
浏览: 146
评论: 0
字数: 16439

在JavaScript中,new关键字用于创建一个新对象,并执行一些初始化操作。

与普通函数相比,构造函数并没有任何特别的地方,首字母大写只是我们约定的小规定,用于区分普通函数.

详解new关键字

new关键字让构造函数具有了与普通函数不同的许多特点,而new的过程中,执行了如下过程:

  • 声明一个中间对象;
  • 将该中间对象的原型指向构造函数的原型;
  • 将构造函数的this,指向该中间对象;
  • 返回该中间对象,即返回实例对象。

模拟new关键字

下面我们通过手写一个 New 函数来模拟 new 关键字的行为:

javascript
// 创建new函数
function New(fun) {
  // 声明一个中间对象,该对象为最终返回的实例
  var res = {};
  if (func.prototype !== null) {
    // 将实例的原型指向构造函数的原型
    res.__proto__ = func.prototype;
  }
}

// 创建一个构造函数
var Person = function (name, age) {
  this.name = name;
  this.age = age;
  this.getName = function () {
    return this.name;
  };
}

// 将构造函数以参数形式传入
function New(func) {
  // 声明一个中间对象,该对象为最终返回的实例
  var res = {};
  if (func.prototype !== null) {
    // 将实例的原型指向构造函数的原型
    res.__proto__ = func.prototype;
  }

  // ret为构造函数执行的结果,这里通过apply,将构造函数内部的this指向修改为指向res,即为实例对象
  var ret = func.apply(res, Array.prototype.slice.call(arguments, 1));

  // 当我们在构造函数中明确指定了返回对象时,那么new的执行结果就是该返回对象
  if ((typeof ret === 'object' || typeof ret === 'function') && ret !== null) {
    return ret;
  }

  // 如果没有明确指定返回对象,则默认返回res,这个res就是实例对象
  return res;
}

// 通过new声明创建实例,这里的p1,实际接收的正是new中返回的res
var p1 = New(Person, 'tom', 20);
console.log(p1.getName());

// 当然,这里也可以判断出实例的类型了
console.log(p1 instanceof Person); // true

代码解释

  • 中间对象的创建:使用 var res = {} 创建一个空对象,作为后续操作的基础。
  • 原型链的设置:通过 res.proto = func.prototype 将中间对象的原型指向构造函数的原型,确保实例能继承原型上的属性和方法。
  • this 绑定与函数执行:使用 func.apply(res, Array.prototype.slice.call(arguments, 1)) 将构造函数的 this 绑定到中间对象 res 上,并传入剩余参数执行构造函数。
  • 返回值判断:检查构造函数的返回值,如果是对象或函数且不为 null,则返回该返回值;否则返回中间对象 res。
点赞
打赏
本文标签:
本文链接:
版权声明:
本文由vscing原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权