_collectNonEnumProps.js 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. var _setup = require('./_setup.js');
  2. var isFunction = require('./isFunction.js');
  3. var _has = require('./_has.js');
  4. // Internal helper to create a simple lookup structure.
  5. // `collectNonEnumProps` used to depend on `_.contains`, but this led to
  6. // circular imports. `emulatedSet` is a one-off solution that only works for
  7. // arrays of strings.
  8. function emulatedSet(keys) {
  9. var hash = {};
  10. for (var l = keys.length, i = 0; i < l; ++i) hash[keys[i]] = true;
  11. return {
  12. contains: function(key) { return hash[key] === true; },
  13. push: function(key) {
  14. hash[key] = true;
  15. return keys.push(key);
  16. }
  17. };
  18. }
  19. // Internal helper. Checks `keys` for the presence of keys in IE < 9 that won't
  20. // be iterated by `for key in ...` and thus missed. Extends `keys` in place if
  21. // needed.
  22. function collectNonEnumProps(obj, keys) {
  23. keys = emulatedSet(keys);
  24. var nonEnumIdx = _setup.nonEnumerableProps.length;
  25. var constructor = obj.constructor;
  26. var proto = isFunction(constructor) && constructor.prototype || _setup.ObjProto;
  27. // Constructor is a special case.
  28. var prop = 'constructor';
  29. if (_has(obj, prop) && !keys.contains(prop)) keys.push(prop);
  30. while (nonEnumIdx--) {
  31. prop = _setup.nonEnumerableProps[nonEnumIdx];
  32. if (prop in obj && obj[prop] !== proto[prop] && !keys.contains(prop)) {
  33. keys.push(prop);
  34. }
  35. }
  36. }
  37. module.exports = collectNonEnumProps;