Classical JavaScript constructors are not equal.

43 views
Skip to first unread message

Nabor

unread,
Apr 9, 2012, 4:35:38 PM4/9/12
to mozilla-la...@googlegroups.com
It has something to do with two different js files.

Test Case 1:

main.js
const arrLanguages = ["de"];

exports.main = function (options, callbacks) {
        console.debug(arrLanguages.constructor);
        if (arrLanguages.constructor === Array) {
            console.debug("It's an Array");
        } else {
            console.debug("Damn, no Array");
        }
}

Result:
=======
debug: function Array() {
    [native code]
}
debug: It's an Array

Testcase 2:

Now doing it with two js files.

main.js
=======
const common = require("common");
const arrLanguages = ["de"];

exports.main = function (options, callbacks) {
  common.checkArray(arrLanguages);
}

common.js
==========
exports.checkArray = function(arr) {
    console.debug(arr.constructor);
    if (arr.constructor === Array) {
        console.debug("It's an Array");
    } else {
        console.debug("Damn, no Array");
    }
};

Result:
=======
debug: function Array() {
    [native code]
}
debug: Damn, no Array

ZER0

unread,
Apr 11, 2012, 8:48:57 AM4/11/12
to mozilla-la...@googlegroups.com
On 04/09/12 22:35 PM, Nabor wrote:

> Testcase 2:

> Now doing it with two js files.
>
> main.js
> =======
> const common = require("common");
> const arrLanguages = ["de"];
>
> exports.main = function (options, callbacks) {
> common.checkArray(arrLanguages);
> }

> common.js
> ==========
> exports.checkArray = function(arr) {
> console.debug(arr.constructor);
> if (arr.constructor === Array) {
> console.debug("It's an Array");
> } else {
> console.debug("Damn, no Array");
> }
> };

That's because the JavaScript context is different, so the globals are
different as well. The `Array` object from `main.js` is not the same of
`common.js`.
So, if you create an array in `main.js`, the `constructor` will be the
`Array` of `main.js`.

If you're familiar with web development, you have the same situation
across frames. That's the main reason because in ES5 you have
`Array.isArray` method:

exports.checkArray = function(arr) {
if (Array.isArray(arr)) {


console.debug("It's an Array");
} else {
console.debug("Damn, no Array");
}
}

Hope it helps.

Nabor

unread,
Apr 11, 2012, 10:33:50 AM4/11/12
to mozilla-la...@googlegroups.com
Sorry, but it doesn't help.
I'm one of these developers how likes to reuse code.
One of my favourite functions is a function that checks if something is in an array.
My reusable functions are put together into one javascript file.
I don't like to copy these function into every other javascript file.
So how can this be solved?
In my opinion it's wrong to say that the constructor Array is not equal to another Array in a different scope.
An Array is an Array and an Object is an Object.
And don't tell me the ugly workarounds like checking if something has a length or making a string compare is a solution.
The fastest and explicit was is to compare the constructors.
But may be you can give me a good reason why an Array from main.js is not equal to an Array from another js within the Addon SDK.

Regards

ZER0

unread,
Apr 11, 2012, 11:07:12 AM4/11/12
to mozilla-la...@googlegroups.com
On 04/11/12 16:33 PM, Nabor wrote:

> My reusable functions are put together into one javascript file.
> I don't like to copy these function into every other javascript file.

You don't have. But if you compare two constructors from different
JavaScript context they cannot be the same. They're different objects.

> In my opinion it's wrong to say that the constructor Array is not equal
> to another Array in a different scope.

It's not a matter of scope, but context. This is how JavaScript works.

> An Array is an Array and an Object is an Object.

Sure, in fact you can check if an Array is an Array using
`Array.isArray` method. It's not something introduced by Add-on SDK,
it's a pure JavaScript method (ES5) that was created for exactly this
purpose.

> And don't tell me the ugly workarounds like checking if something has a
> length or making a string compare is a solution.

I don't. In fact I suggested to you the right method to use, no workarounds.

> The fastest and explicit was is to compare the constructors.

In JavaScript it's not reliable as method, because as you saw you can
end up to compare different objects.

Have a look here:

<http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/>

> But may be you can give me a good reason why an Array from main.js is
> not equal to an Array from another js within the Addon SDK.

As the link described, this behavior is not specific to Add-on SDK, this
is related to JavaScript in general. In Add-on SDK every modules has its
own context � like different iframes.


Nabor

unread,
Apr 18, 2012, 11:38:08 AM4/18/12
to mozilla-la...@googlegroups.com
Sorry, you are absolutely right.
My fault. I did not notice the new features, but will use it from now on.
Reply all
Reply to author
Forward
0 new messages