var _ = require('../utility'); function traverse(obj, func, seen) { var k, v, i; var isObj = _.isType(obj, 'object'); var isArray = _.isType(obj, 'array'); var keys = []; var seenIndex; // Best might be to use Map here with `obj` as the keys, but we want to support IE < 11. seen = seen || { obj: [], mapped: [] }; if (isObj) { seenIndex = seen.obj.indexOf(obj); if (isObj && seenIndex !== -1) { // Prefer the mapped object if there is one. return seen.mapped[seenIndex] || seen.obj[seenIndex]; } seen.obj.push(obj); seenIndex = seen.obj.length - 1; } if (isObj) { for (k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) { keys.push(k); } } } else if (isArray) { for (i = 0; i < obj.length; ++i) { keys.push(i); } } var result = isObj ? {} : []; var same = true; for (i = 0; i < keys.length; ++i) { k = keys[i]; v = obj[k]; result[k] = func(k, v, seen); same = same && result[k] === obj[k]; } if (isObj && !same) { seen.mapped[seenIndex] = result; } return !same ? result : obj; } module.exports = traverse;