2

I have an instance(bar) of a function(foo), but bar.constructor.name returns "Object" instead of "foo". Can anyone tell me what I'm doing wrong?

Code:

function foo(text){
    this.text = text;
}

foo.prototype = {
   getUppercase: function(){
      return this.text.toUpperCase();
    }
}

var bar = new foo("bar");
console.log(bar.constructor.name); //logs "Object" in Chrome
2
  • FWIW bar instanceof foo will return true. This may be a helpful alternative if checking the constructor's actual name isn't a hard requirement in this scenario. Commented Jul 13, 2016 at 18:45
  • @gfullam I didn't need to check if bar was an instance of foo, but just get a string with the constructor name of bar and store it somewhere. Commented Jul 13, 2016 at 19:19

1 Answer 1

2

When you replace the object on a function's prototype property, you have to take responsibility for fixing up the constructor property on it:

foo.prototype = {
  constructor: foo,                  // <====
  getUppercase: function() {
    return this.text.toUpperCase();
  }
};

It's not automatic. The only automatic population of that property is on the default object assigned to the function's prototype property when the function is originally created.

function foo(text){
    this.text = text;
}

foo.prototype = {
  constructor: foo,
  getUppercase: function() {
    return this.text.toUpperCase();
  }
};

var bar = new foo("bar");
console.log(bar.constructor.name);

Alternately, don't replace the default object on prototype, just augment it (usually my preference):

foo.prototype.getUppercase = function() {
    return this.text.toUpperCase();
};

You can do multiple of those via Object.defineProperties or Object.assign (that latter may need a shim) or your own utility function.


Finally, I'd be remiss if I didn't call out a couple of things:

  1. Overwhelmingly, constructor function names start with a capital letter in JavaScript. It is just a convention, but it's a very, very well-established convention.

  2. In ES2015+, you can use class for a more concise version:

  3. Function#name is new as of ES2015 and support is a bit sketchy as I write this in July 2016. (Chrome 51+ does indeed have it.)

FWIW:

class Foo {
    constructor(text) {
        this.text = text;
    }

    getUppercase(){
        return this.text.toUpperCase();
    }
}

var bar = new Foo("bar");
console.log(bar.constructor.name);

Of course, if you need to support older engines (like IE11), you need to transpile if you do that... (But then again, if you're using Function#name, that's from ES2015 too.)

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

4 Comments

I've read about classes in Javascript. I think I'm not going to use it as I want to support older versions of IE, but thanks (again) for your answer.
@qwertytrewq: No worries, glad to help. Beware of using Function#name (that was probably just an example for your question, though, I'm guessing), as it's also new (and not supported in IE11).
I haven't seen the notation Function#name before. Why not refer to it as Function.name with a dot instead of a hash mark?
@gfullam: The # is a convention in JS circles (and I think it's bled over into some others as well) for "a member of instances, possibly via the prototype chain". The property Function.name, literally, has the value "Function" (on a compliant ES2015+ engine). Function#name (or Object#toString, or Date#getdays, etc.) is used to indicate the property isn't on the constructor (Function, Object, Date), but rather the prototype assigned to instances (or in some cases, a property directly assigned to instances).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.