Michael McCauley
Michael McCauley

Reputation: 931

Undefined JavaScript Object Constructor

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).

Upvotes: 2

Views: 4950

Answers (2)

Badacadabra
Badacadabra

Reputation: 8497

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().

Upvotes: 1

Bergi
Bergi

Reputation: 664538

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.

Upvotes: 1

Related Questions