check variable is object

sorry for my english

sometimes you need to check if the variable is a pure object (not an array or function) and so I suggest adding a method for the Object class:

Object.isObject

if (!Object.isObject) {
  Object.isObject = function (i) {
	return Boolean(i) &&
      typeof i === 'object' &&
      !Array.isArray(i)
  }
}

Welcome @MuratovBektur !

Do you think it could be confusing to say that arrays and functions are not objects, when both inherit from Object ?

Maybe you could provide an example of when this check would be useful?

2 Likes

Also by the way, to be safe Array.isArray should be wrapped in a try catch as it can throw an exception.

let {proxy, revoke} = Proxy.revocable([], {});
Array.isArray(proxy); // true
revoke();
Array.isArray(proxy); // TypeError!

I'll ask you a counter question, maybe you could provide an example of when Array.isArray check would be useful?

Js is a dynamic language. From time to time we must check type.

It’s often useful when you want to use array methods and know that a value is a conceptual list.

i could say the same about Object

at the moment we can check all basic types by native methods except object

sure. And you can check that something is a non-array non-function object all you like, but generally it’s easiest to just assume that if it’s an object, it can be used like one, without any “is plain object” check.

Hi @MuratovBektur !

The difference from Array.isArray, is that check narrows down the type considerably. Knowing something is an object but not an array or function has not narrowed down the type by much, it could still be a Map, Set, ArrayBuffer or Object.create(null).

but it is better to be sure that this object is an object and not an array or anything else. I think people use Array.isArray, typeof v = = = 'string' and other type checking methods to make sure the code doesn't break. What is the object so deprived of?

I’m not sure what you mean. There’s typeof, and Array.isArray, and that’s basically it for a direct reliable test. (there’s indirect means, which https://npmjs.com/~inspect-js uses for all its “is-“ predicates.

if you only knew how often newcomers are wrong when checking an object for an object, when checking an array or null that they are an object

previously, arr.indexOf (el)! = = -1 was used to verify the presence of an element in the array, but then arr.includes (el) was added and the code became much clearer. And I would like a more understandable code for checking an object for objects. You ask why check the type of variable on the object, but please watch how many times people on the Internet look for Check if a value is an object in JavaScript(Viewed 1.7m times)

The problem is that “object but not array” isn’t a type, it’s an arbitrary subset of a type. Typeof can be used to check for objects; arrays are objects.

1 Like

If anything, Object.isObject should then be implemented using

typeof x == 'object' && x !== null || typeof x  == 'function'

or using

Object(x) === x

So basically Object.isNotPrimitive. It shouldn't special-case any specific kind of object like array objects, function objects, primitive wrapper objects, regex objects, etc.

1 Like

I could maybe see some value in a utility like this when it comes to JSON? What kinds of values result in {...} in JSON? Arrays don't. Functions don't. Just about any other object does. Dates don't, but they implement their own toJSON and, well, I don't think there's much you can do about that since you don't know what's coming out of that (for any arbitrary object that implements it) unless you call it.

There have also been times where I would have liked to know if an object was an ordinary object or not - something not exotic or with any hidden internal slots/methods that could cause unexpected behavior, irrespective of the prototype chain.

{} // yes
Object.create(null) // yes
Object.setPrototypeOf([], Object.prototype) // no (exotic array)
Object.setPrototypeOf(new String, Object.prototype) // no ([[StringData]] slot)

though I don't recall if there was any practical use for wanting this information or if it was more about curiosity. I suspect the latter.

...though the new String object above is also interesting for the JSON use case since stringify explicitly checks for primitive slots (like [[StringData]]) in objects for conversions. I guess they would also not be considered objects by that definition either.

JSON.stringify(new String('hello')) // "hello"

That’s the problem - unfortunately, the way JS works is that (almost) everything inherits from Object (and null objects don’t inherit from anything). This means that answering the question “is this an object” doesn’t have an answer that’s simultaneously universal/generic, and also useful.

Each individual use case has to answer that themselves, and it wouldn’t make sense for the language to codify just one, or all, of those dozens of rubrics. Thus, things are indeed confusing here for newcomers, and that is both unavoidable and unfixable, due to the nature of the language.

4 Likes

Yeah, so perhaps here we need something a little more concrete than "is this an object", because what @bergus gave would be the canonical way to answer that.

However, this definition will include arrays and what-not, because those are objects, so it makes sense. If we don't include arrays, should we include TypedArray? If we don't include TypedArray should we include userland array classes? If we don't include userland array classes, well, how do avoid doing that?

Perhaps, what you're looking for is just a plain, simple object, the kind of object that you get with an object literal. If it's an instance of any class, you want Object.isObject() to return false. In other words, perhaps you want something like this:

> const isObject = value => Object.getPrototypeOf(value) === Object.prototype
> isObject({ x: 2 })
true
> isObject([])
false

We probably shouldn't call a function like this isObject(), since it's technically returning false for values that really are objects.

And, this will return false for objects that inherit from the null prototype, which is unfortunate. We could consider making a special case for that as well.

1 Like

In 2011 there was a discussion about adding an Object.isObject method, harmony:typeof_null [ES Wiki], which which was primarily focused on fixing typeof null == 'object' semantics, but also should provide some useful context to this proposal thread.

1 Like