2

I've been using the same JavaScript library I've built for years, and now I'm encountering errors with this function:

IsArray : function ()
{
    if (typeof arguments[0] == 'object')
    {
        var criterion = arguments[0].constructor.toString().match(/array/i);
        return (criterion != null);
    }

    return false;
}

There are times when it is called when the following error is thrown:

TypeError: Cannot call method "toString" of undefined

I added the following prior to defining the criterion variable to remedy the issue:

if (arguments[0].constructor == null || arguments[0].constructor == undefined)
    return false;

However, I'd like to understand how or why this would happen. I don't know why a variable that has a type of 'object' would not have a constructor. I've never seen it prior to this issue. And what bothers me about this is this all started a few weeks after I updated another library function that checks for nulls and empty strings to try to filter out empty arrays (when comparing an empty array to an empty string, it was returning a match).

1
  • 5
    null is of type object with typeof. Commented Apr 25, 2017 at 16:24

2 Answers 2

1

Well... As you may know, JavaScript is a bit surprising sometimes. With ES3, it was not easy at all to determine if an array was actually an array. So if you want to keep your legacy code, I think you should follow the great tips given by Douglas Crockford in JavaScript: The Good Parts.

JavaScript does not have a good mechanism for distinguishing between arrays and objects. We can work around that deficiency by defining our own is_array function:

var is_array = function (value) {
  return value && typeof value === 'object' && value.constructor === Array;
};

Unfortunately, it fails to identify arrays that were constructed in a different window or frame. If we want to accurately detect those foreign arrays, we have to work a little harder:

var is_array = function (value) {
  return Object.prototype.toString.apply(value) === '[object Array]';
};

Moreover, you should be very careful when you play with null because Object.create(null) creates an object without any prototype, typeof null returns object and null == undefined returns true...

With ES5, the best solution is to use Array.isArray().

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

4 Comments

ES5 does have Array.isArray. It was only in the olden days that it was really hard.
Nice comment, thanks! You are right. For some reasons, my mind has mixed three specifications on this topic... I thought that Array.isArray() was part of ES6 like Array.from(), but it is part of ES5. The above code was useful in ES3 and older polyfills. I will edit my answer. :)
I had to test this, as I'm working with a server-side JavaScript engine, but it does the trick. My method had worked consistently for years, so I'm glad I can use this now. Odd thing, it worked with one array defined like ["","",""], and then failed a couple lines later with another similar array. So strange.
@Badacadabra Why would someone use Object.create(null)?
1

Not all objects have a .constructor property, e.g. Object.create(null), just like not all objects have a toString method.

For your IsArray function, you should use the native Array.isArray method, or its usual polyfill.

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.