【JavaScript】手撕前端面试题:手写new操作符❗❗❗

前言

当我们在使用构造函数的时候,要实例化一个对象,直接使用new就好了,这样新对象就继承到了构造函数的所有属性和方法。那你有思考过new是啥嘛?它的工作流程是什么样的?这也是在前端面试中经常考的一道手写题,今天就让我们一起拿下它!

new是什么?

在手写new之前,让我们先来好好认识一下new是什么!

new 操作符在 JavaScript 中用于创建一个用户定义的对象类型的实例或已有内置对象类型的实例。

new的执行步骤

1.创建新对象

首先,new 操作符会创建一个新的空对象 {}。这个对象将作为新实例的基础。

  1. 设置原型链

接下来,新创建的对象会被链接到构造函数的 prototype 属性所指向的对象。这意味着新对象将继承构造函数原型上的所有属性和方法。

ini 复制代码
function Person(name) {
this.name = name;
} 
const person1 = new Person('Alice'); 
console.log(person1.__proto__ === Person.prototype); // true

如果你对原型对象与原型链还不是很了解可以先看看我的上一篇文章js原型与原型链(精心总结)(一文搞懂)(建议收藏)❗❗❗

  1. 执行构造函数

然后,构造函数被调用,并且 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
  1. 返回新对象

最后,如果构造函数没有显式返回对象,则 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 做了什么?

  1. 在构造器内部创建一个新的对象
  2. 这个对象内部的隐式原型指向该构造函数的显式原型
  3. 让构造器中的 this 指向这个对象
  4. 执行构造器中的代码
  5. 如果构造器中没有返回对象,则返回上面的创建出来的对象
相关推荐
WYiQIU2 小时前
11月面了7.8家前端岗,兄弟们12月我先躺为敬...
前端·vue.js·react.js·面试·前端框架·飞书
谢尔登2 小时前
简单聊聊webpack摇树的原理
运维·前端·webpack
娃哈哈哈哈呀3 小时前
formData 传参 如何传数组
前端·javascript·vue.js
zhu_zhu_xia4 小时前
vue3+vite打包出现内存溢出问题
前端·vue
tsumikistep4 小时前
【前后端】接口文档与导入
前端·后端·python·硬件架构
行走的陀螺仪4 小时前
.vscode 文件夹配置详解
前端·ide·vscode·编辑器·开发实践
2503_928411565 小时前
11.24 Vue-组件2
前端·javascript·vue.js
Bigger5 小时前
🎨 用一次就爱上的图标定制体验:CustomIcons 实战
前端·react.js·icon
谢尔登5 小时前
原来Webpack在大厂中这样进行性能优化!
前端·webpack·性能优化
g***B7385 小时前
JavaScript在Node.js中的模块系统
开发语言·javascript·node.js