0

I have a created a merging library that merges objects recursively. Sometimes in the middle there would be an object that is actually a special class (like the Timestamp of Firestore).

In my merging function I check if something is an object or not like so:

function isObject (payload) {
  const getType = Object.prototype.toString.call(payload).slice(8, -1)
  return getType === 'Object'
}

However, with this check some special classes with special prototypes are still considered to be regular JavaScript objects.

My problem:
The object will loose its special class prototype because I only go through the non-prototype values to recursively merge.

My question:
How can I change the function above to not only check if it's a JavaScript object, but also check if it's a regular JavaScript object?

Basically I only wanna return true on isObject(obj) if obj is an object like so: {} or with any props.

But once the prototype is different (and thus it's a special class), then I want to return false on isObject(obj)

2 Answers 2

3

In addition to checking the prototype, you can check if its constructor is Object:

const isPlainObject = obj => obj.constructor === Object && Object.getPrototypeOf(obj) === Object.prototype;

const obj1 = { foo: 'bar' };
const obj2 = new Date();
const obj3 = [];
[obj1, obj2, obj3].forEach(obj => console.log(isPlainObject(obj)));

Note that using getPrototypeOf and checking that it is === to Object.prototype is more reliable than using toString - toString may return anything, after all.

If you're going to possibly pass something that's null or undefined to isPlainObject, then of course include a check to see that the obj is truthy before trying to access properties on it:

const isPlainObject = obj => obj && obj.constructor === Object && Object.getPrototypeOf(obj) === Object.prototype;

const obj1 = { foo: 'bar' };
const obj2 = new Date();
const obj3 = [];
[obj1, obj2, obj3].forEach(obj => console.log(isPlainObject(obj)));

Sign up to request clarification or add additional context in comments.

1 Comment

gotta modify your answer a little bit because obj can be null: const isPlainObject = obj => obj && obj.constructor === Object && Object.getPrototypeOf(obj) === Object.prototype;
0

it can be tricky as some javascript types have a typeof "object" like below

console.log(typeof []) // object
console.log(typeof null) // object

A simple way to check for a plain Object is to utilize Object's toString method and also validate for null like this

/**@return boolean */
function isObject(val) {
   const _toString = Object.prototype.toString;
   return val !== null && _toString.call(val) === '[object Object]';
}

now we test this

isObject({}); // true
isObject({a: 2, b: 3}); // true
isObject(null); // false
isObject([]); // false
isObject(new Object()); // true
isObject(new Array()); // false

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.