没对象?new一个呗😝

引言

在JavaScript中,new是一个非常重要的关键字,它用于创建对象实例。虽然new看起来很简单,但它背后隐藏着一些复杂的原理和机制。本文将深入解析JavaScript中的new关键字,介绍其作用、原理,并提供一些代码示例来帮助读者更好地理解。

new关键字的介绍

在JavaScript中,new是一个用于创建对象实例的关键字。当使用new关键字调用一个函数时,它会执行以下操作:

  1. 创建一个空的简单 JavaScript 对象(即 {} );
  2. 为步骤 1 新创建的对象添加属性 __proto__ ,将该属性链接至构造函数的原型对象;
  3. 将步骤 1 新创建的对象作为 this 的上下文;
  4. 如果该函数没有返回对象,则返回 this

语法

js 复制代码
new constructor[([arguments])]

参数

  • constructor

    一个指定对象实例的类型的类或函数。

  • arguments

    一个用于被 constructor 调用的参数列表。

创建一个用户自定义的对象需要两步:

  1. 通过编写函数来定义对象类型。
  2. 通过 new 来创建对象实例。

new关键字的原理

为了更好地理解new关键字背后的原理,我们可以手动实现一个简化版的new操作符。下面是一个示例代码:

javascript 复制代码
function myNew(constructor, ...args) {
  // 创建一个空对象
  const obj = {};

  // 将空对象的原型指向构造函数的prototype属性
  Object.setPrototypeOf(obj, constructor.prototype);

  // 将构造函数内部的this指向这个空对象
  const result = constructor.apply(obj, args);

  // 如果构造函数返回了一个对象,则返回该对象;否则返回新创建的对象
  return typeof result === 'object' && result !== null ? result : obj;
}

通过上述代码,我们可以手动实现一个类似于new关键字的操作。

首先,我们创建一个空对象obj,并将其原型指向构造函数的prototype属性。

然后,我们将构造函数内部的this指向这个空对象,并执行构造函数内部的代码。最后,根据构造函数的返回值决定返回新创建的对象还是该返回值。

new关键字的代码示例

下面是一个使用new关键字创建对象实例的示例代码:

javascript 复制代码
function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.sayHello = function() {
  console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
}

const john = new Person('John', 25);
john.sayHello(); // 输出:Hello, my name is John and I'm 25 years old.

在上述示例中,我们定义了一个Person构造函数,并在其原型上添加了一个sayHello方法。

然后,通过使用new 关键字调用Person构造函数来创建一个名为johnPerson实例。最后,我们调用john 实例上的sayHello方法来输出一段问候语。

new个对象呗

js 复制代码
function Boyfriend(name, age) {
  this.name = name;
  this.age = age;
  this.gender = "male";
  this.isCool = true;
}

function Girlfriend(name, age) {
  this.name = name;
  this.age = age;
  this.gender = "female";
  this.isBeautiful = true;
}

const john = new Boyfriend("John", 25);
const lisa = new Girlfriend("Lisa", 23);

console.log(john); // 输出:Boyfriend { name: 'John', age: 25, gender: 'male', isCool: true }
console.log(lisa); // 输出:Girlfriend { name: 'Lisa', age: 23, gender: 'female', isBeautiful: true }

在上述示例中,我们定义了两个构造函数:Boyfriend和Girlfriend。

这两个构造函数分别用于创建男朋友和女朋友的对象实例。

每个构造函数都接受名字和年龄作为参数,并在对象实例中设置相应的属性(如姓名、年龄、性别和是否正帅气或者漂亮)。通过使用new关键字调用这两个构造函数,我们可以分别创建一个名为john的男朋友对象和一个名为lisa的女朋友对象。最后,我们打印出这两个对象实例,可以看到它们分别具有相应的属性值。

new.target

new.target是一个在构造函数内部可用的元属性(meta property),它提供了一个指向正在被构造的实例的构造函数的引用。它可以用来确定构造函数是通过new关键字被调用还是直接调用。

下面是一些关于new.target的详细介绍:

  1. 使用方式:

    • 在构造函数内部,可以通过访问new.target来获取正在被构造的实例的构造函数。
    • 如果构造函数是通过new关键字被调用,那么new.target将指向该构造函数本身。
    • 如果构造函数是直接调用(而不是通过new关键字),那么new.target将为undefined。
  2. 功能:

    • 可以使用new.target来执行一些特定于构造函数调用的逻辑。例如,可以根据是否使用了new关键字来决定是否执行某些初始化操作。
    • 可以使用new.target来实现基于类的继承。在派生类中,可以通过super关键字和new.target来访问父类的构造函数。

下面是一个示例代码,演示了如何使用new.target:

javascript 复制代码
function Person(name) {
  if (typeof new.target === "undefined") {
    throw new Error("Person must be instantiated using new");
  }
  this.name = name;
}

function Student(name, grade) {
  Person.call(this, name);
  this.grade = grade;
}

Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;

const john = new Person("John"); // 正常调用,创建一个Person实例
console.log(john.name); // 输出:John

const lisa = new Student("Lisa", 10); // 正常调用,创建一个Student实例
console.log(lisa.name); // 输出:Lisa
console.log(lisa.grade); // 输出:10

const mark = Person.call({}, "Mark"); // 错误调用,没有使用new关键字

在上述示例中,我们定义了一个Person构造函数和一个Student构造函数。

在Person构造函数内部,我们使用new.target来检查是否使用了new关键字。如果没有使用new关键字,则抛出一个错误。

在Student构造函数中,我们通过调用Person.call(this, name)来调用父类的构造函数,并传递相应的参数。然后,我们通过Object.create和prototype链来实现基于类的继承。

结论

本文深入解析了JavaScript中的new关键字,介绍了其作用、原理,并提供了一些代码示例来帮助读者更好地理解。通过对new关键字的详细解析,我们可以更好地理解JavaScript中对象实例的创建过程,从而更加灵活地运用new关键字来构建复杂的应用程序。

new.target是一个在构造函数内部可用的元属性,它提供了一个指向正在被构造的实例的构造函数的引用。它可以用来确定构造函数是通过new关键字被调用还是直接调用,并且可以执行特定于构造函数调用的逻辑或实现基于类的继承。

相关推荐
腾讯TNTWeb前端团队6 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰9 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪9 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪10 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy10 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom11 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom11 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom11 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom11 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom11 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试