Ben Aston
Ben Aston

Reputation: 55729

Set the prototype constructor correctly on an object

I have a DTO type that really is a map of key/value pairs. I would typically use an object literal for this for terseness, but this preculdes the resulting object having the [[prototype]].constructor set to a meaningful value.

e.g.

function MyDto() {
    var o = { 
        myProperty: null
    };

    return o; //[[prototype]].constructor is meaningless
}

Is there a way to do something similar, but have the [[prototype]].constructor property set to the more meaningful MyDto (instead of Object)?

Upvotes: 0

Views: 43

Answers (4)

Felix Kling
Felix Kling

Reputation: 816442

To make obj instanceof Foo work, the prototype of obj has to point to the value of the prototype property of the function (Foo). A couple of ways have already been suggested, here is another one:

Call the function with new and return this (implicitly or explicitly). If you want to be able to call the function without new (not really clear from your question), check inside the function whether it was called with new or not:

function MyDto() {
    if (!(this instanceof MyDto)) {
        return new MyDto();
    }
    Object.assign(this, {myProperty: null});
}

Note: The constructor property has no meaning internally, only to the developers using your code.

Upvotes: 1

hon2a
hon2a

Reputation: 7214

You're approaching this from the wrong direction. If you want the result of new Class() be a real instanceof Class, just extend the default instance object, instead of creating and returning a new one.

function Class () {
    _.extend(this, {
        property: 'value',
        // ...
    });
}

(The above code uses Lo-Dash function _.extend() to keep your code short & sweet. Similar implementations may be found in almost all utility libraries or bigger JavaScript frameworks).

Upvotes: 0

Sampath Liyanage
Sampath Liyanage

Reputation: 4896

Not very much sure what you want to do. But this may help..

function MyDto() {
    var o = { 
        myProperty: null
    }; 
    Object.setPrototypeOf(o,MyDto.prototype);
    return o;
}

a = MyDto();
console.log(a);

Upvotes: 1

Danilo Valente
Danilo Valente

Reputation: 11342

I don't think I understand your question, but you might try this:

o.constructor = MyDto;

This will set o's constructor as MyDto, but will have no effect when doing o instanceof MyDto.

If this is what you want, my suggest is that you instantiate MyDto instead:

function MyDto() {
    this.myProperty = null;
}

var o = new MyDto();
console.log(o instanceof MyDto);       // true
console.log(o.constructor === MyDto);  // true

EDIT: If you return within a function, then you will lost the reference to your new instance. In your case MyDto works as a factory to instances of Object that have an own property called myPropert.

EDIT 2: I still prefer the other way, but using Object.create also works:

function MyDto() {
    return Object.create(MyDto.prototype, {
        myProperty: {
            writable: true,
            configurable: true,
            value: null
        }
    });
}

new MyDto() instanceof MyDto;       // true
new MyDto().constructor === MyDto;  // true

Upvotes: 0

Related Questions