前言
当我们在使用构造函数的时候,要实例化一个对象,直接使用new就好了,这样新对象就继承到了构造函数的所有属性和方法。那你有思考过new是啥嘛?它的工作流程是什么样的?这也是在前端面试中经常考的一道手写题,今天就让我们一起拿下它!
new是什么?
在手写new之前,让我们先来好好认识一下new是什么!
new
操作符在 JavaScript 中用于创建一个用户定义的对象类型的实例或已有内置对象类型的实例。
new的执行步骤
1.创建新对象
首先,new
操作符会创建一个新的空对象 {}
。这个对象将作为新实例的基础。
- 设置原型链
接下来,新创建的对象会被链接到构造函数的 prototype
属性所指向的对象。这意味着新对象将继承构造函数原型上的所有属性和方法。
ini 代码解读复制代码function Person(name) {
this.name = name;
}
const person1 = new Person('Alice');
console.log(person1.__proto__ === Person.prototype); // true
如果你对原型对象与原型链还不是很了解可以先看看我的上一篇文章js原型与原型链(精心总结)(一文搞懂)(建议收藏)❗❗❗
- 执行构造函数
然后,构造函数被调用,并且 this
被绑定到新创建的对象上。构造函数可以为新对象添加属性和方法。
javascript 代码解读复制代码function Person(name) {
this.name = name;
this.sayHello = function() {
console.log(`Hello, my name is ${this.name}`);
};
}
const person1 = new Person('Alice');
person1.sayHello(); // 输出: Hello, my name is Alice
4. 返回新对象
最后,如果构造函数没有显式返回对象,则 new
操作符会自动返回新创建的对象。如果有返回值并且是对象类型(包括函数),则返回该对象;如果是非对象类型(如字符串、数字等),则忽略并返回新创建的对象。
javascript 代码解读复制代码function Person(name) {
this.name = name;
// 如果返回的是对象,则返回该对象
return { name: 'Override' };
}
const person1 = new Person('Alice');
console.log(person1.name); // 输出: Override
function AnotherPerson(name) {
this.name = name;
// 如果返回的是非对象类型,则忽略并返回新创建的对象
return 'Not an object';
}
const anotherPerson = new AnotherPerson('Bob');
console.log(anotherPerson.name); // 输出: Bob
手写new
了解完new的执行步骤,那让我们开始直接手写一个new来更好的理解new吧! 第一步 先随便写一个构造函数
js 代码解读复制代码function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayName = function () {
console.log(this.name)
}
在构造函数中我们写了name和age属性,并在Person的原型对象上写了sayName方法。
第二步
要写一个手写new,我的思路就是根据new的四个执行步骤来就行,那么我们第二部就是要创建一个新的空对象
js 代码解读复制代码function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayName = function () {
console.log(this.name)
}
function objectFactory() {
const obj = {};
}
第三步
设置原型链
js 代码解读复制代码function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayName = function () {
console.log(this.name)
}
function objectFactory() {
const obj = {};//空对象的创建
const Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
Constructor.apply(obj, arguments);
}
let awei = objectFactory(Person, 'awei', 23)
console.log(awei);
这里我们用 const Constructor = [].shift.call(arguments);
Constructor来提取第一个参数,let awei = objectFactory(Person, 'awei', 23)
可以看到传入的第一个参数是构造函数Person
这时候我们只需要将空对象的原型指向构造函数的原型对象就完成了原型链的设置了obj.__proto__ = Constructor.prototype;
第四步 设置返回值
js 代码解读复制代码function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayName = function () {
console.log(this.name)
}
function objectFactory() {
const obj = {};
const Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
Constructor.apply(obj, arguments);
return obj;
}
let awei = objectFactory(Person, 'awei', 23)
console.log(awei)
这样我们就实现了new的四个执行步骤,让我们来看看结果吧
总结
new 做了什么?
- 在构造器内部创建一个新的对象
- 这个对象内部的隐式原型指向该构造函数的显式原型
- 让构造器中的 this 指向这个对象
- 执行构造器中的代码
- 如果构造器中没有返回对象,则返回上面的创建出来的对象
评论记录:
回复评论: