JavaScript:中味をあんまり気にしないでディープコピーできる関数

JavaScript:中味をあんまり気にしないでディープコピーできる関数:

前記事の続きです。

引数の中味をあんまり気にしないでディープコピーできる関数cloneです。

前記事ではこう書きました。

const mapForMap = f => a =>  
  new Map( [...a].map( ([key, value]) =>[key, f(value)] ) );   
const mapForSet = f => a => new Set( [...a].map( f ) ); 
const entriesMapIntoObj = f => xs =>  
  xs.reduce( 
    (acc, [key, value]) => ({ ...acc, [key]:f(value) }) 
    , {}  
  ); 
const mapForObj = f => a => 
  entriesMapIntoObj( f )( Object.entries( a ) ); 
const getType = a => Object.prototype.toString.call(a); 
 
const clone = a => { 
  const type = getType( a ); 
  return (type === "[object Array]")?  a.map( clone ) 
        :(type === "[object Map]")?    mapForMap( clone )( a ) 
        :(type === "[object Set]")?    mapForSet( clone )( a ) 
        :(type === "[object Object]")? mapForObj( clone )( a ) 
        :(type === "[object Date]")?   new Date( a ) 
        : a; 
} 
基本的にはこれで動くのですが、込み入ったオブジェクトに使うと動作が鈍いときがあります。

mapForMap,mapForSetで新しい配列を作っては捨てているところがあるので、そこをちょっと節約してみました。

const mapForMap = f => a =>  
  [...a].reduce( (acc,[key, value])=>acc.set(key, f(value)), new Map());  
const mapForSet = f => a =>  
  [...a].reduce((acc, e)=>acc.add(f(e)), new Set()); 
だいぶ動作が速くなった感があります。

さらにforEachで新たに配列を作らない方法にしてみました。

mapForObjでは直接forEachできませんが、なるべく小さい(entries()でなくkeys())配列を作って回すようにしてみました。

const mapForMap = f => a => { 
  const b = new Map(); 
  a.forEach((key, value)=>b.set(key,f(value))); 
  return b; 
} 
const mapForSet = f => a =>{ 
  const b = new Set(); 
  a.forEach(e=>b.add(f(e))); 
  return b; 
} 
const mapForObj = f => a =>{ 
  const b = {}; 
  Object.keys(a).forEach( e => b[e] = f(a[e]) ); 
  return b; 
} 
const getType = a => Object.prototype.toString.call(a); 
 
const clone = a => { 
  const type = getType( a ); 
  return (type === "[object Array]")?  a.map( clone ) 
        :(type === "[object Map]")?    mapForMap( clone )( a ) 
        :(type === "[object Set]")?    mapForSet( clone )( a ) 
        :(type === "[object Object]")? mapForObj( clone )( a ) 
        :(type === "[object Date]")?   new Date( a ) 
        : a; 
} 
実用上はこれで十分かな。

コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)