没对象?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关键字被调用还是直接调用,并且可以执行特定于构造函数调用的逻辑或实现基于类的继承。

相关推荐
fruge2 分钟前
纯css制作声波扩散动画、js+css3波纹催眠动画特效、【css3动画】圆波扩散效果、雷达光波效果完整代码
javascript·css·css3
neter.asia10 分钟前
vue中如何关闭eslint检测?
前端·javascript·vue.js
~甲壳虫11 分钟前
说说webpack中常见的Plugin?解决了什么问题?
前端·webpack·node.js
光影少年30 分钟前
vue2与vue3的全局通信插件,如何实现自定义的插件
前端·javascript·vue.js
As977_31 分钟前
前端学习Day12 CSS盒子的定位(相对定位篇“附练习”)
前端·css·学习
susu108301891133 分钟前
vue3 css的样式如果background没有,如何覆盖有background的样式
前端·css
Ocean☾35 分钟前
前端基础-html-注册界面
前端·算法·html
Rattenking35 分钟前
React 源码学习01 ---- React.Children.map 的实现与应用
javascript·学习·react.js
Dragon Wu37 分钟前
前端 Canvas 绘画 总结
前端
CodeToGym42 分钟前
Webpack性能优化指南:从构建到部署的全方位策略
前端·webpack·性能优化