UNPKG

lodash-compat

Version:

The compatibility build of lodash modular utilities.

137 lines (123 loc) 4.58 kB
var arrayEach = require('../internal/arrayEach'), isArguments = require('../lang/isArguments'), isArray = require('../lang/isArray'), isFunction = require('../lang/isFunction'), isIndex = require('../internal/isIndex'), isLength = require('../internal/isLength'), isObject = require('../lang/isObject'), isString = require('../lang/isString'), support = require('../support'); /** `Object#toString` result references. */ var arrayTag = '[object Array]', boolTag = '[object Boolean]', dateTag = '[object Date]', errorTag = '[object Error]', funcTag = '[object Function]', numberTag = '[object Number]', objectTag = '[object Object]', regexpTag = '[object RegExp]', stringTag = '[object String]'; /** Used to fix the JScript `[[DontEnum]]` bug. */ var shadowProps = [ 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf' ]; /** Used for native method references. */ var errorProto = Error.prototype, objectProto = Object.prototype, stringProto = String.prototype; /** Used to check objects for own properties. */ var hasOwnProperty = objectProto.hasOwnProperty; /** * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objToString = objectProto.toString; /** Used to avoid iterating over non-enumerable properties in IE < 9. */ var nonEnumProps = {}; nonEnumProps[arrayTag] = nonEnumProps[dateTag] = nonEnumProps[numberTag] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true }; nonEnumProps[boolTag] = nonEnumProps[stringTag] = { 'constructor': true, 'toString': true, 'valueOf': true }; nonEnumProps[errorTag] = nonEnumProps[funcTag] = nonEnumProps[regexpTag] = { 'constructor': true, 'toString': true }; nonEnumProps[objectTag] = { 'constructor': true }; arrayEach(shadowProps, function(key) { for (var tag in nonEnumProps) { if (hasOwnProperty.call(nonEnumProps, tag)) { var props = nonEnumProps[tag]; props[key] = hasOwnProperty.call(props, key); } } }); /** * Creates an array of the own and inherited enumerable property names of `object`. * * **Note:** Non-object values are coerced to objects. * * @static * @memberOf _ * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.keysIn(new Foo); * // => ['a', 'b', 'c'] (iteration order is not guaranteed) */ function keysIn(object) { if (object == null) { return []; } if (!isObject(object)) { object = Object(object); } var length = object.length; length = (length && isLength(length) && (isArray(object) || isArguments(object) || isString(object)) && length) || 0; var Ctor = object.constructor, index = -1, proto = (isFunction(Ctor) && Ctor.prototype) || objectProto, isProto = proto === object, result = Array(length), skipIndexes = length > 0, skipErrorProps = support.enumErrorProps && (object === errorProto || object instanceof Error), skipProto = support.enumPrototypes && isFunction(object); while (++index < length) { result[index] = (index + ''); } // lodash skips the `constructor` property when it infers it's iterating // over a `prototype` object because IE < 9 can't set the `[[Enumerable]]` // attribute of an existing property and the `constructor` property of a // prototype defaults to non-enumerable. for (var key in object) { if (!(skipProto && key == 'prototype') && !(skipErrorProps && (key == 'message' || key == 'name')) && !(skipIndexes && isIndex(key, length)) && !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { result.push(key); } } if (support.nonEnumShadows && object !== objectProto) { var tag = object === stringProto ? stringTag : (object === errorProto ? errorTag : objToString.call(object)), nonEnums = nonEnumProps[tag] || nonEnumProps[objectTag]; if (tag == objectTag) { proto = objectProto; } length = shadowProps.length; while (length--) { key = shadowProps[length]; var nonEnum = nonEnums[key]; if (!(isProto && nonEnum) && (nonEnum ? hasOwnProperty.call(object, key) : object[key] !== proto[key])) { result.push(key); } } } return result; } module.exports = keysIn;