Javascript中的New操作、Object.create以及Reflect.construct的对比
Howard 5/11/2021 Javascript
在 JavaScript 中,new
操作符用于创建一个新的对象,新对象将会继承类的所有属性和方法。主要的目标是将新对象的 __proto__
属性指向构造函数的原型,从而实现原型链继承。当我们使用 new
操作符时,实际上会执行以下四个步骤:
- 创建一个新的 JavaScript 对象,并将
this
指向该对象。 - 将新对象的
__proto__
属性指向构造函数的原型(constructor.prototype
),从而实现对原型链上方法和属性的访问。 - 将构造函数内部的赋值属性变成新对象的私有属性。
- 如果构造函数没有返回引用类型的值,则将这个新的 JavaScript 对象返回。
# 使用 Object.create
实现自定义 new
操作符
下面是一个使用 Object.create
方法手写自定义 new
操作符的示例代码:
function newFactory(ctor, ...args) {
if (typeof ctor !== 'function') {
throw new Error('The first parameter of newFactory must be a function');
}
const obj = Object.create(ctor.prototype); // 继承构造函数的原型
const res = ctor.apply(obj, args); // 将私有变量赋值给新对象
const isObject = typeof res === 'object' && res !== null; // 判断是否是引用类型(排除 null)
const isFunction = typeof res === 'function'; // 判断是否是函数
return isObject || isFunction ? res : obj; // 返回引用类型或者函数,否则返回新对象
}
# 使用 [Object.create](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create)
创建新对象
Object.create(proto)
方法是用来创建一个新的对象的,它会将对象的 __proto__
属性指向传入的构造函数。这是一个常用的对象创建方法,也是实现自定义 new
操作符的一种方式。例如:
const person = {
isHuman: false,
printIntroduction: function () {
console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
},
};
const me = Object.create(person); // 创建一个继承自 person 的新对象
me.name = 'Matthew'; // 在新对象上设置属性
me.isHuman = true;
me.printIntroduction(); // 输出: "My name is Matthew. Am I human? true"
# 使用new
操作符实现Object.create
的方法
上面使用 Object.create 方法实现 new,而手写 Object.create 方法也可以用 new 去实现,
Object.mycreate = function (proto, properties) {
function InnerObj() {}
InnerObj.prototype = proto;
if (properties) {
Object.defineProperties(InnerObj, properties);
}
return new F();
};
# 使用 [Reflect.construct()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect/construct)
实现自定义 new
操作符
Reflect.construct()
方法与 new
操作符的行为类似,相当于运行 new target(...args)
。这个方法也可以用于实现自定义的 new
操作符。例如:
function OneClass() {
this.name = 'one';
}
function OtherClass() {
this.name = 'other';
}
// 使用 Reflect.construct() 创建一个对象
var obj1 = Reflect.construct(OneClass, [], OtherClass);
// 等价于使用 Object.create() 创建一个对象并调用构造函数
var obj2 = Object.create(OtherClass.prototype);
OneClass.apply(obj2, []);
你还可以将上面手写的 newFactory
方法改成使用 Reflect.construct()
的方式:
function newFactory(ctor, ...args) {
if (typeof ctor !== 'function') {
throw new Error('The first parameter of newFactory must be a function');
}
let res = Reflect.construct(ctor, args); // 调用构造函数
let isObject =
typeof res === 'object' && res !== null && !(res instanceof Function);
return isObject || typeof res === 'function' ? res : obj;
}
总之,理解 new
操作符的原理以及使用 Object.create
和 Reflect.construct()
可以帮助我们更好地理解 JavaScript 中的对象创建和继承机制。