返回

探秘new原理及构建新式样模拟

前端

我们踏上探险之旅,一起深入解析 ES6 中 Symbol 的魅力与 new 运算符的奥秘,构建模拟实现,从而扩充对 JavaScript 对象创建和类的认识。

揭秘 Symbol 的神韵

ES6 倾情奉献了 Symbol 数据类型,这个全新的成员为我们带来了一系列独到且令人着迷的特性。Symbol 无须借助 new Symbol() 方法就能创建,因为它是一种基本数据类型,其生成的 symbol 值独一无二。当实例化一个类时,隐约可见的私有属性正是 Symbol 大显身手的地方。

举个例子,我们创建一个名为“SecretCode”的 symbol 值,并把它赋给某个对象的私有属性。此时,这个属性只允许我们通过与之关联的 Symbol 值来访问,将Symbol的特征展露无疑。

const secretCode = Symbol();

const obj = {
  [secretCode]: 42
};

console.log(obj[secretCode]); // 输出:42

Symbol 令人惊叹的独特性,在类型检测中闪耀着光芒。它能轻松区分不同实例的 symbol 属性,即使它们的值相同。

揭秘 new 的玄机

new 运算符在 JavaScript 世界中扮演着举足轻重的角色,因为它能够让类中的特殊方法——构造函数——发挥作用。当我们使用 new 调用一个构造函数时,一个从该构造函数的原型继承而来的新对象诞生了。然后,这个新对象将被传给构造函数,作为其 this 的引用。

为了深入理解,我们创建一个名为“Person”的类,包含一个构造函数和一些属性和方法。

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  greet() {
    console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
  }
}

const person1 = new Person('John', 30);
person1.greet(); // 输出:Hello, my name is John and I am 30 years old.

调用 new Person('John', 30) 时,以下过程便应运而生:

  1. 创建一个新的对象,这个对象从 Person.prototype 继承。
  2. 将 this 关键字设置为这个新对象。
  3. 执行 Person 构造函数,并把 this 关键字传给它。
  4. Person 构造函数在 this 对象上设置属性 name 和 age。
  5. Person 构造函数返回 this 对象。

模拟实现

现在,我们将亲手构建一个模拟 new 运算符。

function myNew(constructor, ...args) {
  // 创建一个新对象
  const obj = {};
  // 把该构造函数的原型设置为新对象的原型
  obj.__proto__ = constructor.prototype;
  // 把 this 关键字设置为新对象
  const result = constructor.apply(obj, args);
  // 返回新对象
  return result instanceof Object ? result : obj;
}

// 使用模拟 new 来创建 Person 对象
const person2 = myNew(Person, 'Jane', 25);
person2.greet(); // 输出:Hello, my name is Jane and I am 25 years old.

我们的模拟 new 运算符接受两个参数:要模拟的构造函数和传递给它的参数。我们首先创建一个新的空对象,然后将构造函数的原型设置为新对象的原型。下一步,我们将 this 关键字设置为这个新对象,并调用构造函数。最后,如果构造函数返回了一个对象,我们就返回它,否则,我们就返回这个新对象。

纵览全篇

通过这趟奇妙的旅程,我们领略了 Symbol 和 new 运算符的风采,还动手模拟了 new 运算符,加深了对 JavaScript 中对象创建和类的理解。期待未来有更多精妙绝伦的探索!