From 4621c01afac2f425a6a699919f22fb222786f9cc Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Mon, 28 Mar 2022 16:17:18 -0300 Subject: [PATCH] updated isObject util function --- src/utils/lang/__tests__/index.spec.ts | 34 +++++++++++++------------- src/utils/lang/index.ts | 30 ++++++++++++++++++++--- 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/src/utils/lang/__tests__/index.spec.ts b/src/utils/lang/__tests__/index.spec.ts index e6e724a1..145d4fed 100644 --- a/src/utils/lang/__tests__/index.spec.ts +++ b/src/utils/lang/__tests__/index.spec.ts @@ -231,26 +231,26 @@ test('LANG UTILS / isIntegerNumber', () => { test('LANG UTILS / isObject', () => { // positive - expect(isObject({})).toBe(true); // Should return true for map objects. - expect(isObject({ a: true })).toBe(true); // Should return true for map objects. - expect(isObject(new Object())).toBe(true); // Should return true for map objects. - expect(isObject(Object.create({}))).toBe(true); // Should return true for map objects. - expect(isObject(Object.create(Object.prototype))).toBe(true); // Should return true for map objects. + expect(isObject({})).toBe(true); // Should return true for plain objects (objects created by the Object built-in constructor). + expect(isObject({ a: true })).toBe(true); // Should return true for plain objects. + expect(isObject(new Object())).toBe(true); // Should return true for plain objects. + expect(isObject(Object.create({}))).toBe(true); // Should return true for plain objects. + expect(isObject(Object.create(Object.prototype))).toBe(true); // Should return true for plain objects. // negative - expect(isObject([])).toBe(false); // Should return false for anything that is not a map object. - expect(isObject(() => { })).toBe(false); // Should return false for anything that is not a map object. - expect(isObject(true)).toBe(false); // Should return false for anything that is not a map object. - expect(isObject(false)).toBe(false); // Should return false for anything that is not a map object. - expect(isObject(null)).toBe(false); // Should return false for anything that is not a map object. - expect(isObject(undefined)).toBe(false); // Should return false for anything that is not a map object. - expect(isObject(1)).toBe(false); // Should return false for anything that is not a map object. - expect(isObject('asd')).toBe(false); // Should return false for anything that is not a map object. - expect(isObject(function () { })).toBe(false); // Should return false for anything that is not a map object. - expect(isObject(Symbol('test'))).toBe(false); // Should return false for anything that is not a map object. - expect(isObject(new Promise(res => res()))).toBe(false); // Should return false for anything that is not a map object. + expect(isObject([])).toBe(false); // Should return false for anything that is not a plain object. + expect(isObject(() => { })).toBe(false); // Should return false for anything that is not a plain object. + expect(isObject(true)).toBe(false); // Should return false for anything that is not a plain object. + expect(isObject(false)).toBe(false); // Should return false for anything that is not a plain object. + expect(isObject(null)).toBe(false); // Should return false for anything that is not a plain object. + expect(isObject(undefined)).toBe(false); // Should return false for anything that is not a plain object. + expect(isObject(1)).toBe(false); // Should return false for anything that is not a plain object. + expect(isObject('asd')).toBe(false); // Should return false for anything that is not a plain object. + expect(isObject(function () { })).toBe(false); // Should return false for anything that is not a plain object. + expect(isObject(Symbol('test'))).toBe(false); // Should return false for anything that is not a plain object. + expect(isObject(new Promise(res => res()))).toBe(false); // Should return false for anything that is not a plain object. // Object.create(null) creates an object with no prototype which may be tricky to handle. Filtering that out too. - expect(isObject(Object.create(null))).toBe(false); // Should return false for anything that is not a map object. + expect(isObject(Object.create(null))).toBe(false); // Should return false for anything that is not a plain object. }); diff --git a/src/utils/lang/index.ts b/src/utils/lang/index.ts index 2a7332ff..94efa40d 100644 --- a/src/utils/lang/index.ts +++ b/src/utils/lang/index.ts @@ -150,11 +150,35 @@ export function isNaNNumber(val: any): boolean { return val !== val; } +function _isObject(o: any) { + return Object.prototype.toString.call(o) === '[object Object]'; +} + /** - * Validates if a value is an object with the Object prototype (map object). + * Validates if a value is an object created by the Object constructor (plain object). + * Adapted from: + * + * is-plain-object + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. */ -export function isObject(obj: any): boolean { - return obj !== null && typeof obj === 'object' && obj.constructor === Object; +export function isObject(o: any): boolean { + if (_isObject(o) === false) return false; + + // If has modified constructor + const ctor = o.constructor; + if (ctor === undefined) return false; // `Object.create(null)` + + // If has modified prototype + const prot = ctor.prototype; + if (_isObject(prot) === false) return false; + + // If constructor does not have an Object-specific method + if (Object.prototype.hasOwnProperty.call(prot, 'isPrototypeOf') === false) return false; + + // Most likely a plain Object + return true; } /**