lib/util/object_utils.js
function(val) {
      switch (typeof val) {
        case 'undefined':
        case 'boolean':
        case 'number':
        case 'string':
        case 'symbol':
        case 'function':
          return val;
        case 'object':
        default: {
          // typeof null === 'object'
          if (!val) return val;

          // This covers Uint8Array and friends, even without a TypedArray
          // base-class constructor.
          const isTypedArray =
              val.buffer && val.buffer.constructor == ArrayBuffer;
          if (isTypedArray) {
            return val;
          }

          if (seenObjects.has(val)) {
            return null;
          }

          const isArray = val.constructor == Array;
          if (val.constructor != Object && !isArray) {
            return null;
          }

          seenObjects.add(val);
          const ret = isArray ? [] : {};
          // Note |name| will equal a number for arrays.
          for (const name in val) {
            ret[name] = clone(val[name]);
          }

          // Length is a non-enumerable property, but we should copy it over in
          // case it is not the default.
          if (isArray) {
            ret.length = val.length;
          }
          return ret;
        }
      }
    }
function(val) {
      switch (typeof val) {
        case 'undefined':
        case 'boolean':
        case 'number':
        case 'string':
        case 'symbol':
        case 'function':
          return val;
        case 'object':
        default: {
          // typeof null === 'object'
          if (!val) return val;

          // This covers Uint8Array and friends, even without a TypedArray
          // base-class constructor.
          const isTypedArray =
              val.buffer && val.buffer.constructor == ArrayBuffer;
          if (isTypedArray) {
            return val;
          }

          if (seenObjects.has(val)) {
            return null;
          }

          const isArray = val.constructor == Array;
          if (val.constructor != Object && !isArray) {
            return null;
          }

          seenObjects.add(val);
          const ret = isArray ? [] : {};
          // Note |name| will equal a number for arrays.
          for (const name in val) {
            ret[name] = clone(val[name]);
          }

          // Length is a non-enumerable property, but we should copy it over in
          // case it is not the default.
          if (isArray) {
            ret.length = val.length;
          }
          return ret;
        }
      }
    }
function ( val ) { switch ( typeof val ) { case 'undefined' : case 'boolean' : case 'number' : case 'string' : case 'symbol' : case 'function' : return val ; case 'object' : default : { // typeof null === 'object' if ( ! val ) return val ; // This covers Uint8Array and friends, even without a TypedArray // base-class constructor. const isTypedArray = val . buffer && val . buffer . constructor == ArrayBuffer ; if ( isTypedArray ) { return val ; } if ( seenObjects . has ( val ) ) { return null ; } const isArray = val . constructor == Array ; if ( val . constructor != Object && ! isArray ) { return null ; } seenObjects . add ( val ) ; const ret = isArray ? [ ] : { } ; // Note |name| will equal a number for arrays. for ( const name in val ) { ret [ name ] = clone ( val [ name ] ) ; } // Length is a non-enumerable property, but we should copy it over in // case it is not the default. if ( isArray ) { ret . length = val . length ; } return ret ; } } }
This recursively clones the value |val|, using the captured variable |seenObjects| to track the objects we have already cloned.
This recursively clones the value |val| using the captured variable |seenObjects| to track the objects we have already cloned .