Reputation: 1221
In underscore, there is a collectNonEnumProps:
var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'
];
function collectNonEnumProps(obj, keys) {
var nonEnumIdx = nonEnumerableProps.length;
var constructor = obj.constructor;
var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
// Constructor is a special case.
var prop = 'constructor';
if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
while (nonEnumIdx--) {
prop = nonEnumerableProps[nonEnumIdx];
if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
keys.push(prop);
}
}
}
There is a comment say Constrcutor is a special case
, then use _.has(obj, prop) && !_.contains(keys, prop)
for constructor but prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop))
for other props which not special.
I had tried use prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop))
for constrcutor
. Then npm run test
everything was ok.
var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString', 'constructor'
];
var collectNonEnumProps = function(obj, keys) {
var nonEnumIdx = nonEnumerableProps.length;
var constructor = obj.constructor;
var proto = _.isFunction(constructor) && constructor.prototype || ObjProto;
while (nonEnumIdx--) {
prop = nonEnumerableProps[nonEnumIdx];
if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
keys.push(prop);
}
}
};
So, why underscore
treat constrcutor
special?
Or, it's there any differences between _.has(obj, prop)
and prop in obj && obj[prop] !== proto[prop]
?
Upvotes: 4
Views: 75
Reputation: 141829
Using git blame shows that it was added in a commit with the message "Fix IE non-enumerable properties".
From there, a little more digging revealed that it is to fix this bug in IE 8 and earlier: IE8 property enumeration of replaced built-in properties (e.g. `toString`)
Upvotes: 4