在JavaScript中,new
关键字用于创建一个用户自定义的对象类型的实例或具有构造函数的内置对象的实例。当使用 new
操作符时,JavaScript 会执行以下步骤:
- 创建一个新的空对象。
- 将这个新对象的
__proto__
属性链接到构造函数的prototype
对象。 - 将构造函数的作用域赋给新对象(因此
this
就指向了这个新对象)。 - 如果该函数没有返回其他对象,那么
new
表达式中的函数调用会返回这个新对象。
下面是一个手写的 new
操作符的模拟实现:
function myNew(Constructor, ...args) {
// 1. 创建一个新的空对象
const obj = {};
// 2. 将这个新对象的 __proto__ 属性链接到构造函数的 prototype 对象
obj.__proto__ = Constructor.prototype;
// 使用 Object.create 创建新对象,并设置其原型为构造函数的 prototype
// const obj = Object.create(constructor.prototype);
// 3. 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象)
// 使用 Function.prototype.call 或者 Function.prototype.apply 来调用构造函数
const result = Constructor.apply(obj, args);
// 4. 如果构造函数返回了一个对象,则使用它;否则返回新创建的对象
return result instanceof Object ? result : obj;
}
// 使用示例:
function MyObject(name) {
this.name = name;
}
MyObject.prototype.greet = function() {
console.log(`Hello, my name is ${this.name}!`);
};
// 使用手写的 myNew 来创建 MyObject 的实例
const myObj = myNew(MyObject, 'Alice');
myObj.greet(); // 输出: Hello, my name is Alice!
在这个模拟实现中,我们定义了一个 myNew
函数,它接受一个构造函数和传递给构造函数的参数列表。然后,我们创建了一个新的空对象,并设置其 __proto__
属性指向构造函数的 prototype
对象。接着,我们使用 apply
方法调用构造函数,并将新创建的对象作为 this
的上下文。最后,我们检查构造函数调用的返回值,如果它返回了一个对象,则使用这个返回的对象;否则,返回我们新创建的对象。
请注意,现代JavaScript中更推荐使用 Object.create()
和 Function.prototype.call
或 Function.prototype.apply
来手动模拟 new
操作符的行为,因为直接操作 __proto__
属性在严格模式下是禁止的,并且不是所有环境都支持直接修改 __proto__
属性。此外,Object.create()
方法提供了更直接的方式来创建新对象并设置其原型。