es2015/clone.js
function cloneStructure(keys, getter, setter, traversedValues) {
  for (let key of keys) {
    let value = getter(key)
    let keyClone
    
    if (key instanceof Object) {
      if (traversedValues.has(key)) {
        keyClone = traversedValues.get(key)
      } else {
        keyClone = cloneValue(key, traversedValues)
        traversedValues.set(key, keyClone)
      }
    } else {
      keyClone = key
    }
    
    if (value instanceof Object) {
      if (traversedValues.has(value)) {
        setter(keyClone, traversedValues.get(value))
      } else {
        let clonedValue = cloneValue(value, traversedValues)
        traversedValues.set(value, clonedValue)
        setter(keyClone, clonedValue)
      }
    } else {
      setter(keyClone, value)
    }
  }
}
function cloneStructure(keys, getter, setter, traversedValues) {
  for (let key of keys) {
    let value = getter(key)
    let keyClone
    
    if (key instanceof Object) {
      if (traversedValues.has(key)) {
        keyClone = traversedValues.get(key)
      } else {
        keyClone = cloneValue(key, traversedValues)
        traversedValues.set(key, keyClone)
      }
    } else {
      keyClone = key
    }
    
    if (value instanceof Object) {
      if (traversedValues.has(value)) {
        setter(keyClone, traversedValues.get(value))
      } else {
        let clonedValue = cloneValue(value, traversedValues)
        traversedValues.set(value, clonedValue)
        setter(keyClone, clonedValue)
      }
    } else {
      setter(keyClone, value)
    }
  }
}
function cloneStructure ( keys , getter , setter , traversedValues ) { for ( let key of keys ) { let value = getter ( key ) let keyClone if ( key instanceof Object ) { if ( traversedValues . has ( key ) ) { keyClone = traversedValues . get ( key ) } else { keyClone = cloneValue ( key , traversedValues ) traversedValues . set ( key , keyClone ) } } else { keyClone = key } if ( value instanceof Object ) { if ( traversedValues . has ( value ) ) { setter ( keyClone , traversedValues . get ( value ) ) } else { let clonedValue = cloneValue ( value , traversedValues ) traversedValues . set ( value , clonedValue ) setter ( keyClone , clonedValue ) } } else { setter ( keyClone , value ) } } }
Clones the structure having the specified property keys, using the provided
getters and setters. The function clones the keys and values before setting
them using the setters.

The cloned structure may contain circular references, the function keeps
track of those using the {@code traversedValues} map.

@param {(*[]|{[Symbol.iterator]: function(): {next: function(): *}})} keys
The keys or iterator or iterable object generating the keys to
properties to clone.
@param {function(*): *} getter A callback that returns the value of the
source structure for the provided key.
@param {function(*, *)} setter A callback that sets the provided value (2nd
argument) to the property identified by the specified key (1st
argument) in the structure clone.
@param {Map<Object, Object>} traversedValues A map of traversed
non-primitive keys and values. The keys are the keys and values
traversed in the source structure or structures referencing this
structure, the values are the clones of the keys and values.
Clones the structure having the specified property keys using the provided getters and setters . The function clones the keys and values before setting them using the setters .