How do I wrap a constructor?
Asked Answered
T

1

9

I have this JavaScript:

var Type = function(name) {
    this.name = name;
};

var t = new Type();

Now I want to add this:

var wrap = function(cls) {
    // ... wrap constructor of Type ...
    this.extraField = 1;
};

So I can do:

wrap(Type);
var t = new Type();

assertEquals(1, t.extraField);

[EDIT] I'd like an instance property, not a class (static/shared) property.

The code executed in the wrapper function should work as if I had pasted it into the real constructor.

The type of Type should not change.

Tiruchirapalli answered 11/4, 2012 at 7:14 Comment(4)
By what I understand, you want to add an additional property to the constructor? so that further new instances have that property?Involucrum
May be you need simply to change prototype of Type inside wrap() function. For example: var wrap = function(cls) { cls.prototype.extraField=1; };? Or may be is best to create new Type2 inherited from Type with additional extraField member?Megrim
Can you describe your issue more detail?Teatime
I'd like an instance property, not a class (static/shared) property. The code executed in the wrapper function should work as if I had pasted it into the real constructor.Tiruchirapalli
I
8

update: An updated version here

what you were actually looking for was extending Type into another Class. There are a lot of ways to do that in JavaScript. I'm not really a fan of the new and the prototype methods of building "classes" (I prefer the parasitic inheritance style better), but here's what I got:

//your original class
var Type = function(name) {
    this.name = name;
};

//our extend function
var extend = function(cls) {

    //which returns a constructor
    function foo() {

        //that calls the parent constructor with itself as scope
        cls.apply(this, arguments)

        //the additional field
        this.extraField = 1;
    }

    //make the prototype an instance of the old class
    foo.prototype = Object.create(cls.prototype);

    return foo;
};

//so lets extend Type into newType
var newType = extend(Type);

//create an instance of newType and old Type
var t = new Type('bar');
var n = new newType('foo');


console.log(t);
console.log(t instanceof Type);
console.log(n);
console.log(n instanceof newType);
console.log(n instanceof Type);
Involucrum answered 11/4, 2012 at 7:24 Comment(6)
From your console output, I'd like to extend the function stored in constructor. The new field should show up next to name, not next to constructor.Tiruchirapalli
so what you really want to do is create another constructor? or just add to the existing?Involucrum
I want to extend the existing constructor.Tiruchirapalli
instead of cls.prototype.constructor.call(this, name), I'd do cls.call(this, name). Same function, and no need to worry if the .constructor property is actually present. The danger of foo.prototype = new cls(); is that cls may be a function that requires arguments. That's where foo.prototype = Object.create(cls.prototype) is preferred.Subsellium
@amnotiam interesting. Now I learned something new. But Object.create is ECMA5, how would you do this in older browsers?Involucrum
this example shows the classic fix. It only emulates the "object creation with prototype" part of Object.create, but that's all you need here.Subsellium

© 2022 - 2024 — McMap. All rights reserved.