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]?