Kuzunoha-NEのブログ

プログラミングなどの勉強をしてます

【TypeScript】Objectのディープコピー

こんばんは葛の葉です。

Javascriptのディープコピーをちょっと書きます。Javascriptではconst copyedObj = JSON.parse(JSON.stringify(obj));を使うと思います。

const obj1 = {
  hoge: 1,
  piyo: "hiyoko",
  fuga: true
};

const copyedObj1 = JSON.parse(JSON.stringify(obj1));
obj1.hoge = 2;
console.log(copyedObj1.hoge === 1); // true
console.log(copyedObj1); // { hoge: 1, piyo: 'hiyoko', fuga: true }

しかし、以下のStackOverflowには

Fast cloning with data loss - JSON.parse/stringify

If you do not use Dates, functions, undefined, Infinity, RegExps, Maps, Sets, Blobs, FileLists, ImageDatas, sparse Arrays, Typed Arrays or other complex types within your object, a very simple one liner to deep clone an object is:

 JSON.parse(JSON.stringify(object))

stackoverflow.com

Date型や関数, undefined, Infinityや正規表現、その他もろもろのものについてはコピーできないということです。

const obj2 = {
  moge: undefined,
  date: new Date("2020/01/01Z"),
  func: function () {
    return 'hogehoge';
  },
  reg: /^https/g
};

const copyedObj2 = JSON.parse(JSON.stringify(obj2));
console.log(copyedObj2); // { date: '2020-01-01T00:00:00.000Z', reg: {} };

Date型はJSONになるタイミングでISO 8601形式のstring型になります。正規表現オブジェクトについては、空のオブジェクトに変更されます。こういった一部の型についてはコピーすることが出来ないようです。おそらくJsonが文字列しかないからなのかなぁって思います。

じゃあどうやってディープコピーするの?

先のStackOverflowにも書いてあったんですけど、頑張ってコード書いてもいいけど基本的にライブラリやフレームワークのメソッドを使おうってことみたいです。私が使ったのはこちらのライブラリ。

www.npmjs.com

Typescriptの型はこちら

www.npmjs.com

import clone from "clone";

const obj2 = {
  moge: undefined,
  date: new Date("2020/01/01Z"),
  func: function () {
    return 'hogehoge';
  },
  reg: /^https/g
};

const copyedObj2 = clone(obj2);
console.log(copyedObj2);
/*
{
  moge: undefined,
  date: 2020-01-01T00:00:00.000Z,
  func: [Function: func],
  reg: /^https/g
}
*/ 
console.log(copyedObj2.func()); // hogehoge