Optimize isPlainObject.

Former-commit-id: 37754e27d03929927d8b8653bd7e44ad3ce2b23c
This commit is contained in:
John-David Dalton
2012-08-29 00:05:02 -07:00
parent 2ad9bbae25
commit 4585acf70b
3 changed files with 72 additions and 48 deletions

View File

@@ -798,51 +798,6 @@
return htmlEscapes[match];
}
/**
* Checks if a given `value` is an object created by the `Object` constructor
* assuming objects created by the `Object` constructor have no inherited
* enumerable properties and that there are no `Object.prototype` extensions.
*
* @private
* @param {Mixed} value The value to check.
* @param {Boolean} [skipArgsCheck=false] Internally used to skip checks for
* `arguments` objects.
* @returns {Boolean} Returns `true` if the `value` is a plain `Object` object,
* else `false`.
*/
function isPlainObject(value, skipArgsCheck) {
// avoid non-objects and false positives for `arguments` objects
var result = false;
if (!(value && typeof value == 'object') || (!skipArgsCheck && isArguments(value))) {
return result;
}
// IE < 9 presents DOM nodes as `Object` objects except they have `toString`
// methods that are `typeof` "string" and still can coerce nodes to strings.
// Also check that the constructor is `Object` (i.e. `Object instanceof Object`)
var ctor = value.constructor;
if ((!noNodeClass || !(typeof value.toString != 'function' && typeof (value + '') == 'string')) &&
(!isFunction(ctor) || ctor instanceof ctor)) {
// IE < 9 iterates inherited properties before own properties. If the first
// iterated property is an object's own property then there are no inherited
// enumerable properties.
if (iteratesOwnLast) {
forIn(value, function(objValue, objKey) {
result = !hasOwnProperty.call(value, objKey);
return false;
});
return result === false;
}
// In most environments an object's own properties are iterated before
// its inherited properties. If the last iterated property is an object's
// own property then there are no inherited enumerable properties.
forIn(value, function(objValue, objKey) {
result = objKey;
});
return result === false || hasOwnProperty.call(value, result);
}
return result;
}
/**
* Creates a new function that, when called, invokes `func` with the `this`
* binding of `thisArg` and the arguments (value, index, object).
@@ -1005,6 +960,59 @@
};
}
/**
* Checks if a given `value` is an object created by the `Object` constructor
* assuming objects created by the `Object` constructor have no inherited
* enumerable properties and that there are no `Object.prototype` extensions.
*
* @private
* @param {Mixed} value The value to check.
* @param {Boolean} [skipArgsCheck=false] Internally used to skip checks for
* `arguments` objects.
* @returns {Boolean} Returns `true` if the `value` is a plain `Object` object,
* else `false`.
*/
function isPlainObject(value, skipArgsCheck) {
return value
? value == ObjectProto || (value.__proto__ == ObjectProto && (skipArgsCheck || !isArguments(value)))
: false;
}
// fallback for IE
if (!isPlainObject(objectTypes)) {
isPlainObject = function(value, skipArgsCheck) {
// avoid non-objects and false positives for `arguments` objects
var result = false;
if (!(value && typeof value == 'object') || (!skipArgsCheck && isArguments(value))) {
return result;
}
// IE < 9 presents DOM nodes as `Object` objects except they have `toString`
// methods that are `typeof` "string" and still can coerce nodes to strings.
// Also check that the constructor is `Object` (i.e. `Object instanceof Object`)
var ctor = value.constructor;
if ((!noNodeClass || !(typeof value.toString != 'function' && typeof (value + '') == 'string')) &&
(!isFunction(ctor) || ctor instanceof ctor)) {
// IE < 9 iterates inherited properties before own properties. If the first
// iterated property is an object's own property then there are no inherited
// enumerable properties.
if (iteratesOwnLast) {
forIn(value, function(objValue, objKey) {
result = !hasOwnProperty.call(value, objKey);
return false;
});
return result === false;
}
// In most environments an object's own properties are iterated before
// its inherited properties. If the last iterated property is an object's
// own property then there are no inherited enumerable properties.
forIn(value, function(objValue, objKey) {
result = objKey;
});
return result === false || hasOwnProperty.call(value, result);
}
return result;
};
}
/**
* A shim implementation of `Object.keys` that produces an array of the given
* object's own enumerable property names.