call
在 MDN 中对 new 运算符的解释是:
new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。
为了更清楚理解,举个例子:
1 2 3 4 5 6 7 8 9 10 11 12
| function Car(make, model, year) { console.log(JSON.stringify(this)); console.log(this.__proto__ === Car.prototype); this.make = make; this.model = model; this.year = year; console.log(JSON.stringify(this)); }
const car1 = new Car("Eagle", "Talon TSi", 1993);
console.log(car1.make);
|
在上面的例子中,new 运算符会进行如下操作:
- 创建一个空的简单 JavaScript 对象(即{});
- 新对象的proto属性指向构造函数的 prototype 属性 ;
- 将步骤 1 新创建的对象作为 this 的上下文 ;
- 如果该函数没有返回对象,则返回 this。
模拟实现
实现一个 new 也就意味着不能用 new 关键字,那么要完成这么一系列步骤,我们通过一个函数 newFactory 来实现。
请看下面示例:
1 2 3 4 5 6 7 8 9 10
| function newFactory() { var func = [].shift.call(arguments); var obj = Object.create(func.prototype); var ret = func.apply(obj, arguments); return typeof ret === "object" && ret !== null ? ret : obj; }
|
测试一(构造函数无返回对象):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function Otaku(name, age) { this.name = name; this.age = age;
this.habit = "Games"; }
Otaku.prototype.strength = 60;
Otaku.prototype.sayYourName = function () { console.log("I am " + this.name); };
var person = newFactory(Otaku, "Kevin", "18");
console.log(person.name); console.log(person.habit); console.log(person.strength);
person.sayYourName();
|
测试二(构造函数有返回对象):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| function Otaku(name, age) { this.name = name; this.age = age;
this.habit = "Games"; return { name, age, }; }
Otaku.prototype.strength = 60;
Otaku.prototype.sayYourName = function () { console.log("I am " + this.name); };
var person = newFactory(Otaku, "Kevin", "18");
console.log(person.name); console.log(person.habit); console.log(person.strength);
person.sayYourName();
|
参考文献
https://github.com/mqyqingfeng/Blog/issues/12