深入理解 JavaScript
请支持本书:购买捐赠
(广告,请不要屏蔽。)

14 复制类的实例:.clone() 与 拷贝构造函数



在本章中,我们将介绍两种实现类实例复制的技术

14.1 .clone() 方法

此技术为要复制实例的每个类引入一个 .clone() 方法。它返回 this 的深拷贝。以下示例显示了三个可以克隆的类。

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  clone() {
    return new Point(this.x, this.y);
  }
}
class Color {
  constructor(name) {
    this.name = name;
  }
  clone() {
    return new Color(this.name);
  }
}
class ColorPoint extends Point {
  constructor(x, y, color) {
    super(x, y);
    this.color = color;
  }
  clone() {
    return new ColorPoint(
      this.x, this.y, this.color.clone()); // (A)
  }
}

A 行演示了此技术的一个重要方面:复合实例属性值也必须递归克隆。

14.2 静态工厂方法

*拷贝构造函数*是一种使用当前类的另一个实例来设置当前实例的构造函数。拷贝构造函数在 C++ 和 Java 等静态语言中很流行,在这些语言中,您可以通过*静态重载*提供构造函数的多个版本。在这里,*静态*意味着在编译时就决定使用哪个版本。

在 JavaScript 中,我们必须在运行时做出决定,这会导致代码不优雅

class Point {
  constructor(...args) {
    if (args[0] instanceof Point) {
      // Copy constructor
      const [other] = args;
      this.x = other.x;
      this.y = other.y;
    } else {
      const [x, y] = args;
      this.x = x;
      this.y = y;
    }
  }
}

以下是使用此类的方法

const original = new Point(-1, 4);
const copy = new Point(original);
assert.deepEqual(copy, original);

*静态工厂方法*是构造函数的替代方法,在这种情况下效果更好,因为我们可以直接调用所需的功能。(这里,*静态*意味着这些工厂方法是类方法。)

在以下示例中,三个类 PointColorColorPoint 各有一个静态工厂方法 .from()

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  static from(other) {
    return new Point(other.x, other.y);
  }
}
class Color {
  constructor(name) {
    this.name = name;
  }
  static from(other) {
    return new Color(other.name);
  }
}
class ColorPoint extends Point {
  constructor(x, y, color) {
    super(x, y);
    this.color = color;
  }
  static from(other) {
    return new ColorPoint(
      other.x, other.y, Color.from(other.color)); // (A)
  }
}

在 A 行,我们再次递归复制。

以下是 ColorPoint.from() 的工作原理

const original = new ColorPoint(-1, 4, new Color('red'));
const copy = ColorPoint.from(original);
assert.deepEqual(copy, original);

14.3 致谢