function object inheritance using jquery's extend - javascript

I'm trying to simulate inheritance using jquery extend but as far as I could test, it works only with objects.
What I'm trying to accomplish is:
var baseDefinition = function() {
var self = this;
self.calc1 = function() {
return "something1";
}
self.calc2 = function() {
return "something2";
}
self.myObject = {
propA = 100;
propB = 200;
};
}
var derivedDefinition = function() {
var self = this;
self.calc2 = function() {
return "something different from base";
}
self.myObject = {
propB = 400;
};
}
var instance = $.extend(true, {}, baseDefinition, derivedDefinition);
So I would hope to create a new instance from base definition where the derived definitions would be applied to the base ones but neither definitions would be "touched". Is it possible?
I was hoping to avoid any prototype so basicaly I would like to call instance.calc1 or instance.calc2 without knowing wether it was overriten or not.
Edit:
In my example I didn't include any object properties which was what led me to use jquery's extend function. Although both answers solve inner functions "inheritance", it doesn't (obviously) merge object properties like extend does. As a possible solution I'm thinking after I create my instance to loop through the properties of the instance and apply jquery's extend on them. Although this seems inefficient to me, I don't know if you can advise me on another course of action.

JQuery extend does not create an inheritance hierarchy, so changes you make to base definition AFTER you extend would not be reflected in derived definition. Here's how you can extend the base definition in a way that does reflect later changes down the inheritance hierarchy using Javascript prototypal inheritance:
var baseDefinition = function() {};
baseDefinition.prototype.calc1 = function() {
return "something1";
};
baseDefinition.prototype.calc2 = function() {
return "something2";
};
var derivedDefinition = function() {};
derivedDefinition.prototype = Object.create(baseDefinition.prototype);
derivedDefinition.prototype.calc2 = function() {
return "something different from base";
};
var instance = new derivedDefinition();
instance.calc1(); // something1
instance.calc2(); // something different from base

$.extend only works on already existing objects, not on function which will instantiate objects in the (far?) future:
var instance = $.extend(true, {}, new baseDefinition(), new derivedDefinition());
However, you could of course design an extend function that works for constructors and that returns a function:
function extendConstr() {
var fns = arguments;
return function newConstr(){
var self = {};
for (var i=0; i<fns.length; i++)
fns[i].apply(self, arguments);
return self;
}
}
var extendedFunction = extendConstr(baseDefinition, derivedDefinition);
var instance = extendedFunction();
console.log(instance); // has `calc1` and overwritten `calc2`
Btw, without an extend function you could've done that already manually in the derived constructor:
function derivedDefinition() {
baseDefinition.call(this/*, arguments */);
this.calc2 = function() {
return "something different from base";
}
}
console.log(new derivedDefinition) // has a `calc1` as well

Related

Private prototype methods that can share scope and access the instance

I'm looking for a pattern that both allows me to create a private scope that my function prototype has access to and I need to be able to access the instance from within that scope.
For example, this is how I am currently achieving "private methods" (disregard what the code actually does, just look at the structure.)
function InfoPreview() {
this.element = document.createElement('div');
}
//Private Methods
InfoPreview.prototype.__newLine = function () {
this.element.appendChild(createElement({tagName:'br'}));
};
InfoPreview.prototype.__padLeft = function(level) {
var padding = createElement({tagName: 'span'});
this.element.appendChild(padding);
$(padding).width(level * 10);
};
InfoPreview.prototype.__print = function(string) {
var span = createElement({ tagName: 'span', textContent: string });
this.element.appendChild(span);
this.element.style["margin-right"]='10px';
};
InfoPreview.prototype.__puts = function(string) {
this.__print(string);
this.__newLine();
};
//Public Methods
InfoPreview.prototype.update = function(info) {
$(this.element).empty();
for (var record in info) {
this.__puts(record);
}
};
Notice that I am not creating private methods at all, just utilizing a naming convention. Additionally notice that I have no way to cache chain-lookups, such as this.element.
I would like to create a private scope by utilizing a revealing module pattern, like this:
InfoPreview.prototype = (function() {
var self = this, //<- `this` is actually the global object now.
el = self.element;
var newLine = function () {
el.appendChild(createElement({tagName:'br'}));
};
var padLeft = function(level) {
var padding = createElement({tagName: 'span'});
el.appendChild(padding);
$(padding).width(level * 10);
};
var print = function(string) {
var span = createElement({ tagName: 'span', textContent: string });
el.appendChild(span);
el.style["margin-right"]='10px';
};
var puts = function(string) {
print(string);
newLine();
};
var update = function(info) {
$(el).empty();
for (var record in info) {
puts(record);
}
};
return {
update: update
};
})();
The above approach doesn't work however, because the value of this within the IIFE is the global object, not the instance. I need a way to access the instance.
Is there any downside of using a constructor pattern?
function Foo(constructorArg) {
/* private variables */
var privVar = 'I am private',
cArg = constructorArg;
/* public variables */
this.pubVar = 'I am public';
/* private function */
function privFunc() {
return 'I am a private function';
}
/* public function */
this.publicFunc = function() {
return 'I am a public function and I call privVar->"' + privVar + '" and privFunc->"' + privFunc() + '"';
}
}
var foo = new Foo('something');
console.log('foo.pubVar', foo.pubVar); //ok
console.log('foo.publicFunc()', foo.publicFunc()); // ok
console.log('foo.privVar', foo.privVar); // undefined
console.log('foo.privFunc', foo.privFunc()); //error
Why you should use it (as requested in comments):
Simply put, because it is the only (sane) way of creating a "true private scope", which was your question.
The alternative is using a convention which tell developers what properties and methods are private, usually by prefixing them with an underscore _, which you already implemented but disliked.
Note that constructor and prototype are different things and enable you to do different stuff. Nothing prevents you from mixing both up.
Memory usage
Regarding memory usage, in modern js engines, such as Google's V8 JavaScript Engine, the constructor pattern might actually be faster.
V8 has hidden types created internally for objects at runtime; objects with the same hidden class can then use the same optimized generated code.
For example:
function Point(x, y) {
this.x = x;
this.y = y;
}
var p1 = new Point(11, 22);
var p2 = new Point(33, 44);
// At this point, p1 and p2 have a shared hidden class
p2.z = 55;
// warning! p1 and p2 now have different hidden classes!
Prototype chaining always require two lookups, so it might even be a tiny inny LITTLE bit slower. Note: Can't back up on this, jsperf.com is down!
Constructor pattern is dirty (sic)
Performance was my reason. I hadn't realized that. However it still feels dirty to me
I don't know why you feel the constructor pattern is dirty. Maybe it's because it has some "specifics", limitations and potential pitfalls you should be aware
this can mean different things
It's easy to forget the new keyword causing weird and hard to debug bugs due to shared state
You can't easily split your object across multiple files (without resorting to a build tool or some 3rd party injector)
However, 1 and 2 are also true for prototype declaration style so...
if you feel this is not adequate, you might want to look at the module pattern.
Within each function, you will have access to the this value you want.
var Example = function() {};
Example.prototype = (function() {
var privateUpdate = function() {
document.getElementById('answer').innerHTML = this.foo;
}
return {
update: privateUpdate
}
})();
var e = new Example();
e.foo = 'bar';
e.update();
<div id="answer"></div>
As a variant on what Pointy is suggesting, you can try this pattern;
infoPreview.prototype = (function() {
var self = null;
var update = function(info) {
....
};
var firstUpdate = function(info) {
self = this;
functions.update = update;
update(info);
}
var functions = {
update: firstUpdate
};
return functions;
})();
Maybe something like that, without prototyping :
https://jsfiddle.net/ynwun1xb
var Fn = function(el) {
this.el = el;
var myMethod = function() {
console.log('do something in method with element', this.el);
}.bind(this);
return {
myPublicMethod: function() {
return myMethod();
}
}
}
var instancedFn = new Fn('first instance element')
.myPublicMethod()
;
var instancedFn2 = new Fn('second instance element')
.myPublicMethod()
;

Where/when to set function prototype?

I'm new to javascript prototypes.
In examples, prototypes are assigned in-line with the main program definition, but doing so has start-up sequence ramifications.
The following shows how I currently apply a prototype to a group of singletons. It would be nice to instead assign the prototype within the descendant class, or somewhere more visibly 'bound' to it, for clarity. (Note the panels are instantiated within the controller to enforce separation.)
Is there another location/method to accomplish this I'm overlooking? Also, am I violating any well-known styles with the current approach?
var controller = new Controller();
function Controller() {
var panels = {
search: SearchPanel,
results: ResultsPanel,
details: DetailsPanel,
action: ActionPanel,
};
$.each(panels, function (i, v) {
// THE QUESTION REFERS TO THIS FOLLOWING STATEMENT:
v.prototype = new PanelCommon();
panels[i] = new v();
});
this.publish = function (site, message) {
$.each(panels, function (i, v) {
if (v[site]) v[site](message);
});
}
/*...*/
}
function PanelCommon() { /*...*/ }
function SearchPanel() { /*...*/ }
function ResultsPanel() { /*...*/ }
function DetailsPanel() { /*...*/ }
function ActionPanel() { /*...*/ }
Another fit for the dynamic nature of JavaScript is the concept of Mixins or Augmentation, which are sometimes more natural than prototypical inheritance.
What do I mean by a mixin?
A "mixin" that takes an object, and injects more functionality. Basically, the idea is that we are going to take an object, and start adding behavior to it.
Consider the following mixinPanelTo() function. It'll be a function that takes a constructor and adds a common render() function to it's prototype.
var mixinPanelTo = (function() {
var render = function() {
// a render function that all panels share
console.log("rendering!")
}
// Augment
return function(cls) {
cls.prototype.render = render;
}
})();
Now that we have this, we can mix that functionality into any constructor we want:
var SearchPanel = function() {}
SearchPanel.prototype.search = function(query) {
/* search stuff */
this.render();
}
mixinPanelTo(SearchPanel)
Then, we should be able to
var panel = new SearchPanel()
panel.search("foo"); // "rendering!" on the console
Multiple mixins
One advantage of mixins over inheritance is a more granular control over applied functionality, and also the ability to borrow functionality from multiple parents
var mixinRender = function(cls) { /* inject render */ }
var mixinSearch = function(cls) { /* inject search */ }
var mixinInfiniteScroll = function(cls) { /* inject infinite scroll */ }
var customPanel = function() {}
mixinRender(customPanel);
mixinSearch(customPanel);
mixinInfiniteScroll(customPanel)
This would be difficult to accomplish with prototypical inheritance. Other than trying to make a bizarre class hierarchy.
Borrowing functionality
You can also have your mixin's require functionality/configuration from your target class. For instance, lets take mixinInfinitScroll
var mixinInfiniteScroll = function(cls, fetch) {
var page = 0;
cls.prototype.more = function() {
var data
// get more results
if(typeof fetch == "function")
data = fetch.call(this, ++page)
else
// assume a key in this
data = this[fetch](++page)
/* do work with data */
}
}
And then when mixing in this functionality, we can inject specific functionality:
// by key
var Panel1 = function() { }
Panel1.prototype.fetch = function() { /* go get more results */ }
mixinInifiniteScroll(Panel1, "fetch")
// or even with a direct reference
var Panel1 = function() { }
Panel1.prototype.fetch = function() { /* go get more results */ }
mixinInifiniteScroll(Panel1, Panel1.prototype.fetch)
// or even an anonymous function
var Panel1 = function() { }
mixinInifiniteScroll(Panel1, function() { /* go get more results */ })
Overriding methods
You can also override prototype methods in mixins, which makes them quite powerful
var augmentRender = function(cls, renderFn) {
var oldRender = cls.prototype[renderFn];
cls.prototype[renderFn] = function() {
/* prep */
oldRender.apply(this, arguments);
/* make some more changes */
}
}
And then we can say:
var Panel = function() { }
Panel.prototype.render = function() { /* my render */ }
augmentRender(Panel, "render")
Anyway, not that there is anything wrong with prototypical inheritance, but this might give you some more ideas of different ways to solve your problem by approaching it in a different way.
Usually prototypes are assigned immediately following the declaration of the constructor function. Also, don't forget to modify the constructor property of the newly instantiated prototype.
Sean also makes an interesting point about using Object.create, but whether or not you want to do that really depends on the contents of the PanelCommon constructor function. You also may have to shim Object.create in older browsers.
function PanelCommon() {}
function SearchPanel() {}
SearchPanel.prototype = new PanelCommon();
SearchPanel.prototype.constructor = SearchPanel;
function ResultsPanel() {}
ResultsPanel.prototype = new PanelCommon();
ResultsPanel.prototype.constructor = ResultsPanel;
function DetailsPanel() {}
DetailsPanel.prototype = new PanelCommon();
DetailsPanel.prototype.constructor = DetailsPanel;
function ActionPanel() {}
ActionPanel.prototype = new PanelCommon();
ActionPanel.prototype.constructor = ActionPanel;
You can use Object.create - that will avoid the new SuperClass weirdness of the ES3 solution:
> SearchPanel.prototype = Object.create(PanelCommon.prototype)
> SearchPanel.prototype.constructor = SearchPanel
> new SearchPanel instanceof PanelCommon
true
This can be extracted into a very simple extends function:
function extends(cls, superClass) {
cls.prototype = Object.create(superClass.prototype);
cls.prototype.constructor = cls;
return cls;
}
Which can then be used like this:
var SpecialPanel = extends(function SpecialPanel() {}, PanelCommon);

Names for different Javascript Object Notation

Is there a name for describing the different ways you can define an object in Javascript?
There is this method which is more 'class-like' :
function MyObject() {
this.aMethod= new function(){
};
this.anotherMethod = new function(){
};
}
And this other technique which is more 'dynamic'.
MyObject = new Object();
MyObject.aMethod= new function(){
};
MyObject.anotherMethod = new function(){
};
I have been using both of these techniques in various ways, and i understand the benefits of each, but for the life of me, I don't have any idea how to call these two techniques when discussing this with colleauges.
Do these techniques have names?
In the first case MyObject is a constructor function, since it is supposed to be called with new:
var obj = new MyObject();
In the second case, MyObject is just an object and you assign properties to it. It does not have a special name.
Note that in both cases MyObject has different values. MyObject in the second case is equivalent to obj.
A third way is to use an object initilizer or "object literal":
var obj = {
aMethod: function(){},
anotherMethod: function(){}
};
Your first example is an Object Constructor, while the second is simply adding public methods as properties to an object. As a side note, for an even more "class-like" behavior take a look at the module pattern:
var MyObject = (function() {
var privateStaticVariable = 0;
var my = function() {
var self = this;
var privateInstanceVariable = 0;
function privateInstanceMethod() {
}
self.publicInstanceVariable = 0;
self.publicInstanceMethod = function() {
};
};
function privateStaticMethod() {
};
return my;
});

Crockford's Prototypical Inheritance - Usage

I've been building a small JS framework for use at my job, and I'd like to employ Douglas Crockford's prototypical inheritance patterns. I think I get the general idea of how the prototype object works, but what isn't clear is the way in which I would use this pattern beyond the simplest example.
I'll flesh it out to the point that I understand it.
(function () {
'use strict';
var Vehicles = {};
Vehicles.Vehicle = function () {
this.go = function () {
//go forwards
};
this.stop = function () {
//stop
};
};
Vehicles.Airplane = Object.create(Vehicles.Vehicle());
}());
So now my Vehicles.Airplane object can go() and stop(), but I want more. I want to add takeOff() and land() methods to this object. I could just use ugly dot notation afterwards:
Vehicles.Airplane.takeOff = function () {
//take off stuff
}
But that seems wrong, especially if I were to add many methods or properties. The question asked at here seems to be very similar to mine, but the answer doesn't quite ring true for me. The answer suggests that I should build an object literal before using Object.create, and that I should pass that object literal into the create method. In the example code given, however, it looks like their new object inherits nothing at all now.
What I'm hoping for is some syntax similar to:
Vehicles.Airplane = Object.create(Vehicles.Vehicle({
this.takeOff = function () {
//takeOff stuff
};
this.land = function () {
//land stuff
};
}));
I know this syntax will break terribly with Object.create right now, because of course I'm passing Vehicle.Vehicle a function rather than an object literal. That's beside the point. I'm wondering in what way I should build new properties into an object that inherits from another without having to list them out one at a time with dot notation after the fact.
EDIT:
Bergi, after some anguished thought on the topic, I think I really want to go with what you described as the "Classical Pattern". Here is my first stab at it (now with actual code snippets rather than mocked up hypotheticals - You even get to see my crappy method stubs):
CS.Button = function (o) {
o = o || {};
function init(self) {
self.domNode = dce('a');
self.text = o.text || '';
self.displayType = 'inline-block';
self.disabled = o.disabled || false;
self.domNode.appendChild(ctn(self.text));
if (o.handler) {
self.addListener('click', function () {
o.handler(self);
});
}
}
this.setText = function (newText) {
if (this.domNode.firstChild) {
this.domNode.removeChild(this.domNode.firstChild);
}
this.domNode.appendChild(ctn(newText));
};
init(this);
};
CS.Button.prototype = Object.create(CS.Displayable.prototype, {
constructor: {value: CS.Button, configurable: true}
});
CS.Displayable = function (o) { // o = CS Object
o = o || {};
var f = Object.create(new CS.Element(o));
function init(self) {
if (!self.domAnchor) {
self.domAnchor = self.domNode;
}
if (self.renderTo) {
self.renderTo.appendChild(self.domAnchor);
}
}
//Public Methods
this.addClass = function (newClass) {
if (typeof newClass === 'string') {
this.domNode.className += ' ' + newClass;
}
};
this.addListener = function (event, func, capture) {
if (this.domNode.addEventListener) {
this.domNode.addEventListener(event, func, capture);
} else if (this.domNode.attachEvent) {
this.domNode.attachEvent('on' + event, func);
}
};
this.blur = function () {
this.domNode.blur();
};
this.disable = function () {
this.disabled = true;
};
this.enable = function () {
this.disabled = false;
};
this.focus = function () {
this.domNode.focus();
};
this.getHeight = function () {
return this.domNode.offsetHeight;
};
this.getWidth = function () {
return this.domNode.offsetWidth;
};
this.hide = function () {
this.domNode.style.display = 'none';
};
this.isDisabled = function () {
return this.disabled;
};
this.removeClass = function (classToRemove) {
var classArray = this.domNode.className.split(' ');
classArray.splice(classArray.indexOf(classToRemove), 1);
this.domNode.className = classArray.join(' ');
};
this.removeListener = function () {
//Remove DOM element listener
};
this.show = function () {
this.domNode.style.display = this.displayType;
};
init(this);
};
CS.Displayable.prototype = Object.create(CS.Element.prototype, {
constructor: {value: CS.Displayable, configurable: true}
});
I should be quite clear and say that it's not quite working yet, but mostly I'd like your opinion on whether I'm even on the right track. You mentioned "instance-specific properties and methods" in a comment in your example. Does that mean that my this.setText method and others are wrongly placed, and won't be available to descendant items on the prototype chain?
Also, when used, it seems that the order of declaration now matters (I can't access CS.Displayable.prototype, because (I think) CS.Button is listed first, and CS.Displayable is undefined at the time that I'm trying to reference it). Is that something I'll just have to man up and deal with (put things in order of ancestry in the code rather than my OCD alphabetical order) or is there something I'm overlooking there as well?
Vehicles.Airplane = Object.create(Vehicles.Vehicle());
That line is wrong. You seem to want to use new Vehicles.Vehicle - never call a constructor without new!
Still, I'm not sure which pattern you want to use. Two are coming to my mind:
Classical Pattern
You are using constructor functions just as in standard JS. Inheritance is done by inheriting the prototype objects from each other, and applying the parent constructor on child instances. Your code should then look like this:
Vehicles.Vehicle = function () {
// instance-specific properties and methods,
// initialising
}
Vehicles.Vehicle.prototype.go = function () {
//go forwards
};
Vehicles.Vehicle.prototype.stop = function () {
//stop
};
Vehicles.Airplane = function() {
// Vehicles.Vehicle.apply(this, arguments);
// not needed here as "Vehicle" is empty
// maybe airplane-spefic instance initialisation
}
Vehicles.Airplane.prototype = Object.create(Vehicles.Vehicle.prototype, {
constructor: {value:Vehicles.Airplane, configurable:true}
}); // inheriting from Vehicle prototype, and overwriting constructor property
Vehicles.Airplane.prototype.takeOff = function () {
//take off stuff
};
// usage:
var airplane = new Vehicles.Airplace(params);
Pure Prototypical Pattern
You are using plain objects instead of constructor functions - no initialisation. To create instances, and to set up inheritance, only Object.create is used. It is like having only the prototype objects, and empty constructors. instancof does not work here. The code would look like this:
Vehicles.Vehicle = {
go: function () {
//go forwards
},
stop: function () {
//stop
}
}; // just an object literal
Vehicles.Airplane = Object.create(Vehicles.Vehicle); // a new object inheriting the go & stop methods
Vehicles.Airplane.takeOff = function () {
//take off stuff
};
// usage:
var airplane = Object.create(Vehicles.Airplane);
airplane.prop = params; // maybe also an "init" function, but that seems weird to me
You got Object.create wrong. The first argument should be an object (maybe that's why people suggested you pass a literal).
In your first example, you're actually passing undefined:
Vehicles.Airplane = Object.create(Vehicles.Vehicle()); // the function call will
// return undefined
The following would work, but it's not very Crockford-ish:
Vehicles.Airplane = Object.create(new Vehicles.Vehicle());
The way I believe Crockford would do it (or, at least, wouldn't complain of):
var Vehicles = {};
Vehicles.Vehicle = {
go : function() {
// go stuff
},
stop : function() {
// go stuff
}
};
Vehicles.Airplane = Object.create(Vehicles.Vehicle, {
takeOff : {
value : function() {
// take-off stuff
}
},
land : {
value: function() {
// land stuff
}
}
});
Note that Vehicles.Vehicle is just a literal, which will be used as the prototype for other objects. When we call Object.create, we pass Vehicles.Vehicle as the prototype, and takeOff and land will be own properties of Vehicles.Airplane. You may then call Object.create again, passing Vehicles.Airplane as the prototype, if you want to create e.g. a Boeing.
The own properties passed as the second parameter are packed in an object that contains a representation of their property descriptors. The outer keys are the names of your properties/methods, and each one points to another object containing the actual implementation as the value. You may also include other keys like enumerable; if you don't they'll take the default values. You can read more about descriptors on the MDN page about Object.defineProperty.

Javascript prototype banals: inheritance

How can i override this.property at runtime and for each instance, without making a new class and eventually calling doAnotherThing on the parent?
var ThridPartyObject = function() {
this.property = 'value';
this.doOneThing= function() { /* */ }
this.doAnotherThing= function() { /* */ }
};
No luck with:
ThridPartyObject.prototype = {
property: 'myvalue',
doOneThing: function() { // Override only this function and call the other
return this.doAnotherThing();
}
};
EDIT: forgot to say that property may or may not exists.
I need this because, in backbone.js, i have to define a custom property for all my model instances, and some function should act in a different way of original backbone ones. Here is how backbone defines a Backbone.Model (_.extend is from underscore.js):
var Model = Backbone.Model = function(attributes, options) {
var defaults;
attributes || (attributes = {});
if (options && options.collection) this.collection = options.collection;
if (options && options.parse) attributes = this.parse(attributes);
if (defaults = getValue(this, 'defaults')) {
attributes = _.extend({}, defaults, attributes);
}
this.attributes = {};
this._escapedAttributes = {};
this.cid = _.uniqueId('c');
this.changed = {};
this._silent = {};
this._pending = {};
this.set(attributes, {silent: true});
// Reset change tracking.
this.changed = {};
this._silent = {};
this._pending = {};
this._previousAttributes = _.clone(this.attributes);
this.initialize.apply(this, arguments);
};
// Attach all inheritable methods to the Model prototype.
_.extend(Model.prototype, Events, {
// cut
});
If the object is truly "third party," and outside your control, then the creators of it have chosen a pattern that is not compatible with prototypal inheritance (sometimes called the "closure pattern"). You will not be able to override, globally, any properties of ThirdPartyObject instances, because every ThirdPartyObject gets property, doOneThing, and doAnotherThing newly assigned to it at construction time.
In this case the only solution would be to create a new factory function wrapping the original:
function modifiedThirdPartyObjectFactory() {
var x = new ThirdPartyObject();
x.property = "myvalue";
return x;
}
var mtpo = modifiedThirdPartyObjectFactory();
A pattern that does use prototypal inheritance would work as follows:
function ThirdPartyObject() {
this.property = "value";
}
ThirdPartyObject.prototype.doOneThing = function () {
};
ThirdPartyObject.prototype.doAnotherThing = function () {
};
This pattern sets instance properties, usually data, in the constructor. Whereas shared properties, usually methods, go on the prototype. The original code made all properties instance properties, so there are no shared properties you can modify that would result in your changes being reflected across all instances.
You're actually thinking about it backwards.
Prototype would be like the parent class.
It's not exactly-like the parent class in a class-based language (there are a LOT of differences).
But in this instance, for the sake of inheriting properties/methods, prototype would be the parent class.
When you make a Foo, Foo is the child, for all intent and purpose in your problem.
When you do this:
function Foo () { this.method = function () {}; this.property = {}; }
Foo.prototype.method = function () {};
Foo.prototype.property = {};
Foo.prototype.other_property = 3;
It's similar to saying:
PrototypeClass {
public virtual property = {};
public other_property = 3;
public virtual method ( ) { }
}
Foo inherits BaseClass {
public override property = {};
public override method () {}
}
var foo = new Foo();
The constructor for Foo is overriding everything up the chain in the prototype, that has the same name.
When Foo doesn't have a method or a property inside of it, THEN it looks upstream, through its inheritance/prototype chain.
So if you want to override methods/properties of Foo, then you MUST override the instance of new Foo().
Your options for that are pretty much just to build a wrapper around Foo... ...like:
function FooPlusPlus () {
var foo = new Foo();
foo.plus = function () { this.doSomething(); console.log(this.val); };
foo.plusPlus = function () { foo.plus(); console.log(this.other_val); };
return foo;
}
var fooPlusPlus = FooPlusPlus(); // ***NO NEW***
...or to create a function which simply extends a pre-existing object (whether it's a "class" or a "dictionary" or a function, or an array) with whatever added properties/functionality you want to extend them with:
var extendObj = function (subject, extensions) {
var key = "";
for (key in extensions) { if (extension.hasOwnProperty(key)) {
subject[key] = extensions[key];
}}
}
var regularFoo = new Foo();
extendObj(regularFoo, { awesomeFunc : function () { if (typeof this.doSomething === "function") { this.doSomething(); }}, coolProp : "Bob" });
JS gives you the freedom to let anything inherit anything, as long as you aren't expecting strings or numbers to act like classes with custom data, without careful manipulation of the Core objects.

Categories

Resources