8000 Optimize `isPlainObject`. · lodash/lodash@4585acf · GitHub
[go: up one dir, main page]

Skip to content

Commit 4585acf

Browse files
committed
Optimize isPlainObject.
Former-commit-id: 37754e27d03929927d8b8653bd7e44ad3ce2b23c
1 parent 2ad9bba commit 4585acf

File tree

3 files changed

+72
-48
lines changed

3 files changed

+72
-48
lines changed

build.js

Lines changed: 18 additions & 3 deletions
< E30A tr class="diff-line-row">
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@
435435
* @returns {String} Returns the `isArguments` fallback snippet.
436436
*/
437437
function getIsArgumentsFallback(source) {
438-
return (source.match(/(?:\s*\/\/.*)*\s*if *\(noArgsClass[\s\S]+?};\s*}/) || [''])[0];
438+
return (source.match(/(?:\s*\/\/.*)*\n( +)if *\(noArgsClass[\s\S]+?};\n\1}/) || [''])[0];
439439
}
440440

441441
/**
@@ -563,7 +563,18 @@
563563
* @returns {String} Returns the source with the `isFunction` fallback removed.
564564
*/
565565
function removeIsFunctionFallback(source) {
566-
return source.replace(/(?:\s*\/\/.*)*\s*if *\(isFunction\(\/x\/[\s\S]+?};\s*}/, '');
566+
return source.replace(/(?:\s*\/\/.*)*\n( +)if *\(isFunction\(\/x\/[\s\S]+?};\n\1}/, '');
567+
}
568+
569+
/**
570+
* Removes the `isPlainObject` fallback from `source`.
571+
*
572+
* @private
573+
* @param {String} source The source to process.
574+
* @returns {String} Returns the source with the `isPlainObject` fallback removed.
575+
*/
576+
function removeIsPlainObjectFallback(source) {
577+
return source.replace(/(?:\s*\/\/.*)*\n( +)if *\(!isPlainObject[\s\S]+?};\n\1}/, '');
567578
}
568579

569580
/**
@@ -984,6 +995,11 @@
984995
return match.replace(/\bcallee\b/g, 'merge');
985996
});
986997

998+
if (!isUnderscore) {
999+
source = removeIsArgumentsFallback(source);
1000+
source = removeIsPlainObjectFallback(source);
1001+
}
1002+
9871003
// remove `hasDontEnumBug`, `hasObjectSpliceBug`, `iteratesOwnLast`, `noArgsEnum` assignment
9881004
source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var hasDontEnumBug\b[\s\S]+?}\(1\)\);\n/, '');
9891005

@@ -1006,7 +1022,6 @@
10061022
source = removeVar(source, 'iteratorTemplate');
10071023
source = removeVar(source, 'noArraySliceOnStrings');
10081024
source = removeVar(source, 'noCharByIndex');
1009-
source = removeIsArgumentsFallback(source);
10101025
source = removeKeysOptimization(source);
10111026
source = removeNoArgsClass(source);
10121027
source = removeNoNodeClass(source);

build/pre-compile.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@
106106
'_',
107107
'_chain',
108108
'_wrapped',
109+
'__proto__',
109110
'after',
110111
'all',
111112
'amd',

lodash.js

Lines changed: 53 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -798,51 +798,6 @@
798798
return htmlEscapes[match];
799799
}
800800

801-
/**
802-
* Checks if a given `value` is an object created by the `Object` constructor
803-
* assuming objects created by the `Object` constructor have no inherited
804-
* enumerable properties and that there are no `Object.prototype` extensions.
805-
*
806-
* @private
807-
* @param {Mixed} value The value to check.
808-
* @param {Boolean} [skipArgsCheck=false] Internally used to skip checks for
809-
* `arguments` objects.
810-
* @returns {Boolean} Returns `true` if the `value` is a plain `Object` object,
811-
* else `false`.
812-
*/
813-
function isPlainObject(value, skipArgsCheck) {
814-
// avoid non-objects and false positives for `arguments` objects
815-
var result = false;
816-
if (!(value && typeof value == 'object') || (!skipArgsCheck && isArguments(value))) {
817-
return result;
818-
}
819-
// IE < 9 presents DOM nodes as `Object` objects except they have `toString`
820-
// methods that are `typeof` "string" and still can coerce nodes to strings.
821-
// Also check that the constructor is `Object` (i.e. `Object instanceof Object`)
822-
var ctor = value.constructor;
823-
if ((!noNodeClass || !(typeof value.toString != 'function' && typeof (value + '') == 'string')) &&
824-
(!isFunction(ctor) || ctor instanceof ctor)) {
825-
// IE < 9 iterates inherited properties before own properties. If the first
826-
// iterated property is an object's own property then there are no inherited
827-
// enumerable properties.
828-
if (iteratesOwnLast) {
829-
forIn(value, function(objValue, objKey) {
830-
result = !hasOwnProperty.call(value, objKey);
831-
return false;
832-
});
833-
return result === false;
834-
}
835-
// In most environments an object's own properties are iterated before
836-
// its inherited properties. If the last iterated property is an object's
837-
// own property then there are no inherited enumerable properties.
838-
forIn(value, function(objValue, objKey) {
839-
result = objKey;
840-
});
841-
return result === false || hasOwnProperty.call(value, result);
842-
}
843-
return result;
844-
}
845-
846801
/**
847802
* Creates a new function that, when called, invokes `func` with the `this`
848803
* binding of `thisArg` and the arguments (value, index, object).
@@ -1005,6 +960,59 @@
1005960
};
1006961
}
1007962

963+
/**
964+
* Checks if a given `value` is an object created by the `Object` constructor
965+
* assuming objects created by the `Object` constructor have no inherited
966+
* enumerable properties and that there are no `Object.prototype` extensions.
967+
*
968+
* @private
969+
* @param {Mixed} value The value to check.
970+
* @param {Boolean} [skipArgsCheck=false] Internally used to skip checks for
971+
* `arguments` objects.
972+
* @returns {Boolean} Returns `true` if the `value` is a plain `Object` object,
973+
* else `false`.
974+
*/
975+
function isPlainObject(value, skipArgsCheck) {
976+
return value
977+
? value == ObjectProto || (value.__proto__ == ObjectProto && (skipArgsCheck || !isArguments(value)))
978+
: false;
979+
}
980+
// fallback for IE
981+
if (!isPlainObject(objectTypes)) {
982+
isPlainObject = function(value, skipArgsCheck) {
983+
// avoid non-objects and false positives for `arguments` objects
984+
var result = false;
985+
if (!(value && typeof value == 'object') || (!skipArgsCheck && isArguments(value))) {
986+
return result;
987+
}
988+
// IE < 9 presents DOM nodes as `Object` objects except they have `toString`
989+
// methods that are `typeof` "string" and still can coerce nodes to strings.
990+
// Also check that the constructor is `Object` (i.e. `Object instanceof Object`)
991+
var ctor = value.constructor;
992+
if ((!noNodeClass || !(typeof value.toString != 'function' && typeof (value + '') == 'string')) &&
993+
(!isFunction(ctor) || ctor instanceof ctor)) {
994+
// IE < 9 iterates inherited properties before own properties. If the first
995+
// iterated property is an object's own property then there are no inherited
996+
// enumerable properties.
997+
if (iteratesOwnLast) {
998+
forIn(value, function(objValue, objKey) {
999+
result = !hasOwnProperty.call(value, objKey);
1000+
return false;
1001+
});
1002+
return result === false;
1003+
}
1004+
// In most environments an object's own properties are iterated before
1005+
// its inherited properties. If the last iterated property is an object's
1006+
// own property then there are no inherited enumerable properties.
1007+
forIn(value, function(objValue, objKey) {
1008+
result = objKey;
1009+
});
1010+
return result === false || hasOwnProperty.call(value, result);
1011+
}
1012+
return result;
1013+
};
1014+
}
1015+
10081016
/**
10091017
* A shim implementation of `Object.keys` that produces an array of the given
10101018
* object's own enumerable property names.

0 commit comments

Comments
 (0)
0