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