Reputation: 12717
I am creating a new class based on the Base
class binded with external methods from the ext
obj.
function Base(info) {
var self = this;
self.name = info.name;
self.createNewInstance = function (data) {
//I would like to identify the parent constructor
// in this case, the obj containing `filter` and `find` methods
// and use that to generate a new instance
return new self.constructor(data);
};
return self;
}
var ext = {
filter: function () {/*...*/},
find: function () {/*...*/}
},
FinalClass = Base.bind(ext),
instance1 = FinalClass({name: 'John'}),
instance2 = instance1.createNewInstance({name: 'Mark'});
console.log(instance1);
//--> {name: 'John', filter: [Function], find: [Function], createNewInstance: [Function]}
console.log(instance2);
//--> {name: 'Mark'}
But as you can see I would like to create new instance from inside the FinalClass
class which will be able to use the binded methods and not only the Base
class ones.
So instance2
would also have filter
, find
and createNewInstance
methods.
I would be using different types of classes that inherit the same Base
class, so just hardcode the bind method in there wouldn't work I'm afraid :(
Is this possible to achieve?
Thanks in advance
Upvotes: 1
Views: 588
Reputation: 25332
I'm afraid there some misunderstanding about how javascript works. Let's analyze the code:
var ext = {
filter: function () {/*...*/},
find: function () {/*...*/}
},
FinalClass = Base.bind(ext),
So, here you have a Base
function bound to ext
. It means, every time you call FinalClass
, this
will be ext
.
instance1 = FinalClass({name: 'John'}),
Here you're call FinalClass
passing an object with name
equal to 'John'. Because in Base
you have:
function Base(info) {
var self = this;
self.name = info.name;
// ...
return self;
}
And this
is the instance of ext
in FinalClass
, it means you're adding a new property name
to ext
object. And I think you don't want that.
Then you returns self
, it means you're returning ext
again.
After that, you have:
instance2 = instance1.createNewInstance({name: 'Mark'});
Let's have a look to that method:
self.createNewInstance = function (data) {
return new self.constructor(data);
};
Because instance1
it wasn't create using new
operator, and it's ext
itself, it means its constructor is Object
, not FinalClass
as you probably expected.
I believe you can find a better way to do what you want using prototypal inheritance and Object.create. However, you should be able to obtain the result you're looking for using a code similar to the follow:
function Base(info) {
this.name = info.name;
this.createNewInstance = function (data) {
return new this.constructor(data);
};
return this;
}
var ext = {
filter: function () {/*...*/},
find: function () {/*...*/}
};
function FinalClass(info) {
var object = Object.create(ext);
object.constructor = FinalClass;
return Base.call(object, info);
}
var instance1 = FinalClass({name: 'John'}),
instance2 = instance1.createNewInstance({name: 'Mark'});
console.log(instance1);
console.log(instance2);
// notice that `filter` and `find` won't probably be listed because are not "own properties", but the objects have them:
console.log(instance1.filter);
console.log(instance2.filter);
You could also write a utility method in Base
that generalize a bit that work, so your code will looks like:
function Base(info) {
this.name = info.name;
this.createNewInstance = function (data) {
return new this.constructor(data);
};
return this;
}
Base.create = function(extension) {
return function Extendend () {
var object = Object.create(extension);
object.constructor = Extendend;
return Base.apply(object, arguments);
}
}
var ext = {
filter: function () {/*...*/},
find: function () {/*...*/}
};
var FinalClass = Base.create(ext);
var instance1 = FinalClass({name: 'John'}),
instance2 = instance1.createNewInstance({name: 'Mark'});
Hope it helps, if you have doubts or I misunderstood your question, just let me know!
Upvotes: 2