跳到主要内容

new 实例化的重写

在 JavaScript 中,我们通常使用new关键字来创建一个构造函数的实例对象。但是,你知道吗?我们可以通过重写Function.prototype.new方法来自定义new的实现过程。下面我就来讲解一下如何重写new方法。

首先,我们在Function的原型对象上添加一个new方法:

Function.prototype.new = function () {
// this指向调用new方法的构造函数对象
var fn = this;
// 为obj添加原型
var obj = Object.create(fn.prototype);
// 修改this指向,指向obj,传入arguments
// 构造函数执行,把传入的参数赋值到obj上,成为obj的属性
var res = fn.apply(obj, arguments);
// 判断res是否继承于Object
return res instanceof Object ? res : obj;
};

我们来一步步分析上面的代码:

  1. 首先获取到调用new方法的构造函数对象,赋值给变量fn

  2. 然后使用Object.create方法创建一个新对象obj,并将构造函数的原型对象赋值给obj的原型。这样obj就继承了构造函数的原型属性和方法。

  3. 接着使用apply方法修改构造函数内部this的指向,让它指向新创建的对象obj,并把arguments参数传递进去。这样构造函数内部的this就指向了obj,所以构造函数内部的属性都会被赋值到obj上,成为obj的属性。

  4. 构造函数执行完后会返回一个对象res,我们判断它是否继承于Object,如果是则直接返回res,否则返回obj

这样我们就实现了new操作符的内部逻辑。下面我们来测试一下:

function Person(name, age) {
this.name = name;
this.age = age;
}

Person.prototype.say = function () {
console.log('hello');
};

var p = Person.new('zhangsan', 18);
console.log(p); // Person {name: "zhangsan", age: 18}
p.say(); // hello