1

I ran into a problem using instanceof in JavaScript:

var MyObject = function() {
    var prop = {}; 
    return prop;
}

var testObject = new MyObject();
console.log(testObject instanceof MyObject); // return false;

Instanceof returns Object instead of the expected MyObject. I can't remove "return prop"; How can I get the type MyObject for testObject ?

Thanks for helping

EDIT: Even if my question looks like this one: What's wrong with a JavaScript class whose constructor returns a function or an object, mine needed a bit more explanation about what a new does.

Community
  • 1
  • 1
Barudar
  • 560
  • 4
  • 13
  • possible duplicate of [What's wrong with a JavaScript class whose constructor returns a function or an object](http://stackoverflow.com/questions/29006893/whats-wrong-with-a-javascript-class-whose-constructor-returns-a-function-or-an) – connexo Aug 03 '15 at 15:27

4 Answers4

2

You could probably break it into steps based on what the new operator does

var MyObject = function () {
    var prop = {};
    return prop;
}

var testObject = Object.create(MyObject.prototype);
var result = MyObject.call(testObject);
// result is the actual output of new MyObject();
result = result && typeof result === 'object' ? result : testObject;

console.log(testObject instanceof MyObject); // returns true
console.log(result instanceof MyObject); // returns false because it's actually prop (i.e. {})

What we have done is replace the new with the actual steps that happen when you do a new. Below are the steps

  1. Create an object whose prototype is the same as the function's (constructor's) prototype. This is what var testObject = Object.create(MyObject.prototype);

  2. Call the (constructor) function with this set to this newly created object. This what var result = MyObject.call(testObject); does (the first parameter being the value of this for the MyObject invocation)

  3. If the function returns a non null object, the new ... expression evaluates to that value. Otherwise it evaluates to the object created in Step 1.


For the question, the last step's non null return value (prop = {}) was getting in the way of our actually testing the type of the object returned in Step 1. By splitting it into component steps we can get the created object (and use that in the instanceOf test)

potatopeelings
  • 40,709
  • 7
  • 95
  • 119
  • It works, but I don't fully understand why... I will dig into that and tomorrow I will check if I can use it, but I think it will be good. Thanks !! – Barudar Aug 03 '15 at 16:21
  • It's what I needed, thanks! And I fully understand your answer now, thanks again =) – Barudar Aug 05 '15 at 09:17
1

If you can at least modify prop, then you could add a flag to it:

var MyObject = function() {
    var prop = { _isMyObject: true }
    return prop;
};

Then you could have a function that checks for that flag.

function isMyObject(obj) {
    return obj._isMyObject ? true : false;
}
Josiah Keller
  • 3,635
  • 3
  • 23
  • 35
  • Yes, it's exactly what i wanted to do at first, but I wanted to try something else without adding another property, but thanks. – Barudar Aug 03 '15 at 16:18
0

You will see why if you try this:

var MyObject = function() {
    var prop = { testProp: 1 }; 
    return prop;
}

var testObject = new MyObject();
console.log(testObject.testProp); // returns 1;

If in a class constructor you return an object, the newly instantiated object of that will become that returned object. If you return a primitive value, it will instead become an instance of the object as your originally expected.

So, if you apply Object.prototype.toString() method on your prop object and instead return the result of that (a string primitive), you get your desired MyObject back:

var MyObject = function() {
    var prop = {}; 
    return prop.toString();
}

var testObject = new MyObject();
console.log(testObject instanceof MyObject); // returns true;
connexo
  • 53,704
  • 14
  • 91
  • 128
  • That's the way it works. Can you at least wrap that return statement in for example a `getter` function? – connexo Aug 03 '15 at 16:22
-3

It's because when you do

var MyObject = function() {
    var prop = {}; 
    return prop;
}

you are assigning a function to the variable MyObject. Not creating a custom object MyObject. In order to create a custom object, you need to use the syntax

function MyObject() {
    var prop = {}; 
    return prop;
}

var testObject = new MyObject();
console.log(testObject instanceof MyObject); // return true;

Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof

Jake Dluhy
  • 617
  • 6
  • 19
  • A constructor *is* a function. – Josiah Keller Aug 03 '15 at 15:25
  • this doesn't even work. + both ways are fine to declare a function. – Enjoyted Aug 03 '15 at 15:27
  • Edited to reflect the proper wording. The original way defines a function, my way defines a class. – Jake Dluhy Aug 03 '15 at 15:29
  • It doesn't return true, tested in f12. And, I may be wrong, I think that the main difference between the two ways of declaring a function is whether it's assigned or not. Doing my way, MyObject will not be hoisted. – Barudar Aug 03 '15 at 16:15
  • Huh, thanks for the feedback Barudar. I actually tested it before I posted but I guess I did something different in the test. – Jake Dluhy Aug 03 '15 at 18:41