Skip to content
目录

目录:

本章,我们将看2个用于实现对类实例的拷贝的技术

  • .clone() 方法
  • 所谓的 拷贝构造器(copy constructors,构造器接收另一个当前类的实例,然后用它初始化当前实例

1️⃣ .clone()方法

这个技术在需要被拷贝的类中引入一个 .clone() 方法。它返回一个 this(即类实例) 的深拷贝。下面示例,展示了3个可被拷贝的类。

js
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 展示了这个技术的一个重点:复合实例属性值必须递归地克隆

2️⃣ 静态工厂方法

👩🏻‍🏫 拷贝构造器 是使用当前类的另一个实例来设置当前实例的构造器。

TIP

拷贝构造器在一些静态语言,比如C++,Java等语言中比较流行,你可以通过 静态重载(static overloading 的方式提供多个版本的构造器。这里,静态 意味着在编译时选择使用哪个版本。

在JS中,我们必须在运行时做出决定,这也导致一些不优雅的代码😅

js
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
    }
  }
}

使用:

js
const original = new Point(-1, 4)

// 💡传入另一个Point实例到构造器中创建当前实例 实现对original实例的拷贝
const copy = new Point(original)

assert.deepEqual(copy, original)

静态工厂方法(static factory methods 是构造器的另一种方式,并且效果更好,因为我们可以直接调用想要的功能🤩。(这里,静态 表示工厂方法是类方法)

下面示例,3个类 Point, Color & ColorPoint 每个都有一个静态工厂方法 .from():

js
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 exentds 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 我们再一次递归的拷贝了💡。

示例:

js
const original = new ColorPoint(-1, 4, new Color('red'))
// 静态工厂方法创建副本
const copy = ColorPoint.from(original)

assert.deepEqual(copy, original)

3️⃣ 鸣谢(Acknowledgements)

Ron Korvig 提醒我在JavaScript中使用静态工厂方法,而不是重载构造函数进行深度复制。

总结(译者注):

  • 本章提供了2种类实例拷贝的2种方式
  • clone() 方法中调用构造器创建新的实例,返回当前类 this 的深拷贝
  • 静态工厂方法拷贝,一般命名 static from(other) {},类似于 Array.from() (推荐😎)

2022年07月27日23:50:51