在 JavaScript 里,new 操作符是创建对象实例的常用方式。不过,你是否好奇它内部是如何工作的呢?这篇文章会详细剖析 new 操作符的原理,还会手把手教你手写一个 new 函数。
什么是 new 操作符
在 JavaScript 中,new 操作符的用途是创建一个用户自定义对象类型的实例,或者创建一个内置对象类型的实例。咱们先看一个简单的例子:
ini
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayName = function() {
console.log(`My name is ${this.name}`);
};
const john = new Person('John', 30);
john.sayName();
在这个例子中,new Person('John', 30) 创建了一个 Person 构造函数的实例 john。new 操作符完成了以下几个关键步骤:
- 创建新对象:一个全新的对象被创建出来。
- 设置原型:新对象的原型会被设置为构造函数的 prototype 属性。
- 执行构造函数:构造函数会在新对象的上下文中执行,也就是说,构造函数里的 this 会指向新对象。
- 返回新对象:如果构造函数没有显式返回一个对象,那么就返回新创建的对象。
手写 new 函数
接下来,我们要自己实现一个 new 函数,以此来深入理解 new 操作符的工作原理。以下是实现代码:
javascript
function objectFactory() {
console.log(arguments,arguments.length);
const obj = new Object();
//arguments 类数组对象,没有shift方法
// 1.将类数组对象转化为数组对象
// 2.数组对象调用shift方法
// 3.将shift方法返回的结果赋值给Constructor
// 4.删除数组对象的第一个元素
const Constructor = [].shift.call(arguments);
console.log(Constructor);
obj.__proto__ = Constructor.prototype;
Constructor.apply(obj, arguments);
console.log(obj);
return obj;
}
代码解释
- 创建新对象:
ini
const obj = new Object();
这行代码创建了一个全新的空对象。
- 获取构造函数:
ini
const Constructor = [].shift.call(arguments);
arguments 是一个类数组对象,它包含了传递给 objectFactory 函数的所有参数。我们借助 [].shift.call(arguments) 把 arguments 的第一个元素取出来,这个元素就是构造函数。
- 设置原型:
ini
obj.__proto__ = Constructor.prototype;
这行代码把新对象 obj 的原型设置为构造函数的 prototype 属性,这样新对象就可以继承构造函数原型上的属性和方法了。
- 执行构造函数:
arduino
Constructor.apply(obj, arguments);
使用 apply 方法在新对象 obj 的上下文中执行构造函数,这样构造函数里的 this 就会指向新对象。
- 返回新对象:
kotlin
return obj;
最后,返回新创建的对象。
使用自定义的 new 函数
ini
let shuai = objectFactory(Person, "小帅", 20);
console.log(shuai.name);
shuai.sayName();
在这个例子中,我们用 objectFactory 函数创建了一个 Person 构造函数的实例 shuai。可以看到,shuai 对象拥有 name 属性,并且能调用 sayName 方法。
总结
通过手写 new 函数,我们对 new 操作符的工作原理有了更深入的理解。new 操作符本质上就是创建一个新对象,设置其原型,执行构造函数,最后返回新对象。掌握这个原理,有助于你更好地理解 JavaScript 中的面向对象编程。
希望这篇文章能帮助你理解 JavaScript 中 new 操作符的原理和实现方式。如果你有任何疑问或者建议,欢迎在评论区留言。