index.js 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. 'use strict';
  2. var isPlainObject = require('is-plain-object');
  3. var defaults = require('object.defaults/immutable');
  4. module.exports = function(obj, fn, opts) {
  5. if (!isObject(obj)) {
  6. return;
  7. }
  8. if (typeof fn !== 'function') {
  9. return;
  10. }
  11. if (!isPlainObject(opts)) {
  12. opts = {};
  13. }
  14. forEachChild(obj, '', fn, 0, opts);
  15. };
  16. function forEachChild(node, baseKey, fn, depth, opts) {
  17. var keys = Object.keys(node);
  18. if (typeof opts.sort === 'function') {
  19. var sortedKeys = opts.sort(keys);
  20. if (Array.isArray(sortedKeys)) {
  21. keys = sortedKeys;
  22. }
  23. }
  24. depth += 1;
  25. for (var i = 0, n = keys.length; i < n; i++) {
  26. var key = keys[i];
  27. var keyChain = baseKey + '.' + key;
  28. var value = node[key];
  29. var nodeInfo = defaults(opts);
  30. nodeInfo.name = key;
  31. nodeInfo.index = i;
  32. nodeInfo.count = n;
  33. nodeInfo.depth = depth;
  34. nodeInfo.parent = node;
  35. var notDigg = fn(value, keyChain.slice(1), nodeInfo);
  36. if (notDigg || !isPlainObject(value)) {
  37. continue;
  38. }
  39. forEachChild(value, keyChain, fn, depth, opts);
  40. }
  41. }
  42. function isObject(v) {
  43. return Object.prototype.toString.call(v) === '[object Object]';
  44. }