MDN 上描述如下:
- 创建一个空的简单Javascript对象 (即{ })
2. 将构造函数赋给该空对象的constructor - 链接空对象的原型和构造函数的原型 (设置该构造函数的prototype为新创建空对象的
__proto__
) - 将新创建的对象作为
this
的上下文(即将构造函数的作用域赋给新对象) - 如果该构造函数没有返回对象,则返回
this
我认为 第二步 应该和网上大多数说的一样,将构造函数的原型传递给新建对象的隐式原型(
__proto__
),如果是将构造函数直接赋值给新建对象的隐式原型上的constructor
那么这个构造出来的新对象,还具有原生对象的一些属性。如下图:
根据MDN和网上参考的一些解释,得出如下实现的代码
const customNew = (constructor) => {
let obj = {}
obj.__proto__ = constructor.prototype
return function () {
constructor.apply(obj, arguments)
return obj
}
}
然后让我们来使用一下
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayName = function() {
console.log(this.name);
}
let person1 = new Person("ming", 12)
let person2 = customNew(Person)("hong", 11)
console.log(Person.prototype);
console.log(person1);
console.log(person2);
貌似功能都完善得差不多了,但是如果构造函数有返回值的话就会出错了
function Person(name, age) {
this.name = name;
this.age = age;
return {
age: this.age
}
}
结合构造函数的内部原理:
- 在函数体前隐式加上
this = {}
, - 执行
this.xxx = xxx
- 隐式返回 this
最终代码如下:
const customNew = (constructor) => {
//1. 创建一个空的简单Javascript对象 (即{ })
let obj = {}
//2. 将构造函数的原型和对象的原型关联
obj.__proto__ = constructor.prototype
return function () {
//3. 为新创建的对象添加属性
const res = constructor.apply(obj, arguments)
if(res instanceof Object) { //4. 如果该构造函数没有返回对象,则返回 this
return res
} else {
return obj
}
}
}
具体使用:
function Foo(name) {
this.name = name;
}
let obj = customNew(Foo)("obj");
console.log(obj);
网友评论