Javascript prototype method override not found - javascript

I have this base type:
typeA = function () {
};
typeA.prototype = {
do = function() { alert ("do something"); },
doMore = function() { this.do(); }
}
and an inherited type typeB:
typeB = function () {
};
typeB .prototype = new typeA();
typeB.prototype.do = function() { alert ("do something else"); };
When I create an instance of typeB and call doMore, I get an error indicating that this.do is not a function. Can I do this sort of thing in Javascript?

Is this example what you are looking for?
typeA = function () { };
typeA.prototype = {
do : function() { alert ("do something"); }, //use : instead of = here
doMore : function() { this.do(); }
}
typeB = function () { };
typeB.prototype = new typeA();
typeB.prototype.do = function() { alert ("do something else"); };
var instance = new typeB();
instance.doMore();
You use : when declaring the properties of an object and = when assigning values to variables. :D
Additional explanation:
This is where the interesting stuff happens:
typeB.prototype = new typeA();
When you access a function or variable of an object with ., the browser first looks in the object itself to see if that variable is defined there. This is why you can do things like this:
var foo = function() {};
foo.prototype.bar = 3
instance = new foo();
alert( instance.bar ); //alerts 3
instance["bar"] = 55; //add a variable to the instance object itself
alert( instance.bar ); //alerts 55, instance variable masks prototype variable
This shows how there are two ways that something can be 'in' an object. It can either be in the object itself (which you can also do by adding this.bar = 55 to the constructor) or it can in the object's prototype.
Hence, when you say typeB.prototype = new typeA(); you are putting everything in that instance of typeA into typeB'prototype. What you've basically said is "Hey browser, if you can't find something in an instance of typeB, look to see if its in this instance of typeA!"
Turns out there's nothing actually in that instance, just things in its prototype that end up getting used when the browser can't find a variable of that name in that object itself. When you call instance.doMore(), the browser can't find it in instance, so it looks in typeB.prototype, which you just set to an instance of typeA. Since it can't find anything called doMore in that instance, it looks in its prototype, and finally finds a definition for doMore and happily calls it.
One interesting thing is that you can still mess around with things that are actually in that instance of typeA that you set to be the prototype:
//earlier code the same
foo = new typeA();
typeB.prototype = foo;
foo.do = function() { alert ("do something else"); };
//^^ same as `typeB.prototype.do = function() { alert ("do something else"); };`
var instance = new typeB();
instance.doMore();
While this is kind of cool when you understand what's going on IMHO, the extra layer of indirection (checking to see if stuff is defined in the instance of typeA before looking in typeA.prototype) is probably not the best idea, and your code would probably be clearer if you just said this:
typeB.prototype = typeA.prototype;
(sorry if you already knew everything I just told you, but I thought I'd describe how things were working under the hood ;)

You cannot use the word do because it is a reserved keyword (used in do while loop). You can, however, try this:
typeA.prototype = {
"do": function() { ... }
...
};
typeA["do"]();

It is better if you use constructor functions when working with prototypes.
What you have to do is instantiate the object be after you set its prototype of typeA. What you're doing is dynamically adding they new function of .do() to be after typeB is created. That is the only way you can do that.
function typeA() { };
typeA.prototype = {
'do': function () { alert("do something"); },
doMore: function () { this.do(); }
}
function typeB() { };
typeB.prototype = new typeA();
typeB.prototype['do'] = function () { alert('doing from typeB'); };
var b = new typeB();
//
b.do();

Related

Classes inside object literals

I was just not sure how to search this out despite many tries, so forgive me if this has been answered before.
The question is simple: can I create an instance of class window.A.class() as window.B?
To clarify, I have an object literal holding all my data for a browser game:
var gameName = {
environment: function() {
this.place = "...";
// ...
// ...
},
game: function() {
this.player = function() {
// ...
}
}
// and so on...
}
Could I create a window-level gameName.environment() instance with var A = new gameName.environment()? Are there any restrictions to creating an object-bound class's instance outside the class' parent object?
It doesn't really matter in this case how/where a function is defined. Consider these two examples:
function Foo() {}
var obj = {
bar: Foo
};
and
var obj = {
bar: function () { }
};
As far as the function and the object are concerned, those two examples are equivalent. So no, there is no problem calling a function assigned to an object property with new. All you need is a reference to the function, it doesn't matter how you get that reference.
You could do
var Environment = gameName.environment;
var A = new Environment();
if you like that better, but that's totally unnecessary.

Javascript prototype on properties

I'd like to have an object with multiple levels of methods and properties. The top level will have properties and methods. Some of these properties will then act as name-spaces for second level methods and properties.
e.g.
//first level methods
base.doStuff();
base.doMore();
//second level methods
base.level2.doStuff();
Doing the first level is straight forward:
function Base(foo) {
this.foo = foo;
}
Base.prototype.doStuff = function () {
console.log(this.foo);
}
Base.prototype.doMore = function () {
console.log(this.foo);
}
base = new Base("bar");
base.doStuff();
Is it possible to get a second level, where in the function expression the "this" keyword points back to the Base constructor?
It's much easier to do this without prototypes:
function Base() {
var base = this;
base.level2 = {
moreStuff: function() {
// use "base" instead of "this" here
}
};
}
This can be combined with either prototypical methods, as in your example, or methods defined directly on base in the constructor. The downside of this is that you are creating the method functions every time you instantiate a new object, so you miss some of the shared-prototype goodness of standard prototypical methods.
You could create a new prototype-based object to be your level2:
function Level2() {}
Level2.prototype.moreStuff = function() {
// do stuff
}
function Base() {
this.level2 = new Level2();
}
But the methods of base.level2 won't be bound to base unless you bind them explicitly. Various libraries have bind support (e.g. Underscore's _.bind), or you can do it in plain JS:
function Base() {
var base = this;
base.level2 = new Level2();
base.level2.moreStuff = function() {
return Level2.prototype.moreStuff.apply(base, arguments);
}
}
You could further simplify here, but you're always going to have to make new methods bound in one way or another, because JS is never going to assign this in base.level2.moreStuff() to base without explicit binding - so in most cases the first option is the easiest and cleanest.
But really, is it worthwhile just for namespacing? If there's no functional value, it's a lot harder than simply calling your methods level2MoreStuff(), etc.
Well,
base.doStuff();
is calling doStuff in context of base. It is the same as
base.doStuff.call(base);
You can call and apply any function, for overriding this:
var base = new Base();
var someFun = function () {
console.log (this === base); // true
};
someFun.call(base);
Further anonymous example:
var anObj = {
method0: function () {
console.log (this === anObj); // true
}
};
anObj.method1 = function () {
console.log (this === anObj); // true
};
anObj.method0();
anObj.method1();
So the "second level" points this to level2, not to the "first level" object.
This is a really bad idea, but here goes:
function Base() {
this.name = 'Base';
this.level2 = new Level2(this);
}
Base.prototype.whatsMyName = function(){
alert(this.name);
};
function Level2(base) {
this.name='Level2';
for(var func in Level2.prototype) {
this[func] = Level2.prototype[func].bind(base);
}
}
Level2.prototype.whatsMyName = function(){
alert(this.name);
};
var b = new Base();
b.whatsMyName(); //Base
b.level2.whatsMyName(); //Also Base
You can see it running here: http://jsfiddle.net/zLFgd/1/

JavaScript prototypal inheritance workaround

Here is an example:
var Box = function() {
this.id = generateUniqueId();
};
Box.prototype = {
add:function(parent) {
parent.appendChild(this.elm);
}
};
var NewBox = function() {
this.newThing = true;
};
NewBox.prototype = new Box();
NewBox.prototype.remove = function() {
this.elm.parentNode.removeChild(this.elm);
};
var a = new NewBox();
var b = new NewBox();
alert(a.id); // alerts 0
alert(b.id); // also alerts 0! :#
I would like to have a and b (basically each time I create a NewBox) have their own id. I understand that NewBox is using prototypal inheritance and is thus inheriting from a single instance of the generated id that it gets from Box, but I would like it so that each NewBox gets its own id without having to explicitly say that inside the NewBox constructor.
Maybe it's impossible or I'm doing something really wrong, so please help!
Thanks a lot!
In your example, the Box constructor gets executed only when you set the NewBox.prototype object.
You could workaround this by calling the Box constructor function inside NewBox with the Function.prototype.apply method, to set the this value and forward all the argument values, for example:
//..
var NewBox = function() {
Box.apply(this, arguments);
this.newThing = true;
};
//..
var a = new NewBox();
var b = new NewBox();
// assuming your `generateUniqueId` function
// increments a number
alert(a.id); // will alert 1
alert(b.id); // will alert 2
Now, each time the NewBox constructor is called to create a new object instance (new NewBox();), it will call the Box function to apply all its logic on it. This will help you to avoid repeating the logic of the parent constructor over and over.
The apply, is used call the "parent" constructor function setting the this value to the object instance that is being created by the NewBox constructor and we pass all arguments provided to this function.
Your example also shows a common problem, when you express inheritance relationship through NewBox.prototype = new Box(); the Box constructor gets called and it has side effects, this new object will be initialized and your generateUniqueId function will be executed for the first time, if you want to avoid that, you need to either use a temp constructor, just to make a new object that inherits from Box.prototype, or use the new ECMAScript 5 Object.create method for the same purpose, for example:
function inherit(o) {
function Tmp() {}
Tmp.prototype = o;
return new Tmp();
}
//.....
NewBox.prototype = inherit(Box.prototype);
Or:
NewBox.prototype = Object.create(Box.prototype);
In that way, you express the same inheritance hierarchy without running your Box constructor that first time, avoiding any side effect that it might cause.
At last but not least, whenever you replace a function's prototype property is always recommended to restore the constructor property of this new prototype object, otherwise it will point to the wrong function.
In your example, since you replace the NewBox.prototype with a new instance of Box, the NewBox.prototype.constructor property will point to Box, (your instances are affected, e.g. a.constructor === Box; // true) instead of to NewBox as you would expect, we need to set it back, e.g.:
NewBox.prototype = someObject; // as any of the examples above
NewBox.prototype.constructor = NewBox;
You could abstract those details into a function, as I did in the inherit function above:
function inherits(child, parent) {
var obj, Tmp = function () {};
Tmp.prototype = parent.prototype;
obj = new Tmp();
child.prototype = obj;
child.prototype.constructor = child;
}
//...
// instead of setting the `NewBox.prototype` manually
inherits(NewBox, Box); // "NewBox inherits from Box"
//...
Maybe it's impossible or I'm doing something really wrong, so please help!
You're doing something wrong.
If you want instance-specific values, initialize them in the constructor, not the prototype.
Matt Ball has the right idea. Instead try:
var Box = (function(){
var numberOfBoxes = 0;
function() {
this.id = numberOfBoxes++;
}
})();
Or in the case you want all your (different) classes to have unique ids:
var generateUniqueID = (function(){
var runningCount = 0;
return function (){
return runningCount++;
}
})();
var Box = function() {
this.id = generateUniqueId();
};
var NewBox = function() {
this.id = generateUniqueId();
this.newThing = true;
};

Is there a good pattern for JavaScript calling overridden functions in a parent without knowing the specific parent?

Basically I want inheritable functions as in
Base = function() { };
Base.prototype.foo = function() {
console.log("base foo");
};
Derived = function() { };
somelib.inherit(Derived, Base);
Derived.prototype.foo = function() {
console.log("derived foo");
}
d = new Derived():
d.foo();
And I want it to print
derived foo
base foo
Yes I know I can explicitly call Base.prototype.foo.call(this); I'm just wondering if there is a pattern for calling overridden super class functions automatically. The problem I'm trying to solve is 2 fold.
derived classes should NOT have to remember to call their parent's method, it just happens automatically.
if 1. can't happen then at least I'd like Derived not to call Base by name since that's brittle. Rather I'd like it call parentclass or something so you don't have to know the base. That way if you change the name of the base you don't have to go fixing every derived class.
You can implement such functionality by using a structure like:
function Base(){}
Base.prototype.destroy = function(){console.log('Base destroy');};
function Derived(){}
Derived.prototype = new Base; // Let Derived inherit from Base
// Override the `destroy` method
Derived.prototype.destroy = function() {
console.log('Derived destroy');
// Call parent class method
this.constructor.prototype.destroy();
// If the context of the method is important, you can use Function.call:
//this.constructor.prototype.destroy.call(this);
};
// Create an instance of Derived, and call the destroy method:
(new Derived).destroy();
I would suggest thinking about exactly why you are doing this, at least in terms of requirement #1. Keep in mind that your desired pattern would take away a great deal of flexibility. For instance, if you have a situation where you want to print the statements in the opposite order:
base foo
derived foo
You would either have to abandon your pattern or create a function foo2() in the derived class which then calls foo() in the base class. Neither is very pretty.
Same goes if you even want to do something as simple as:
derived foo
base foo
one more thing in the derived function
I would contend that using this pattern may work for the exact thing you want to do right now, but may give you fits when you want to make a seemingly trivial change down the road. All to save one line of code!
As far as I know there is no language integrated destructor functionality in JavaScript. It is all about frameworks. If you are using ASP.NET Ajax, for example, the framework would expect that your objects would have a dispose method, responsible for freeing up resources (event handlers). So, it is up to you.
Ok, this isn't quite what you are looking for, in that it's not a "pattern", but it is a potential implementation path you could follow:
Take a look # the MooTools Class.Extras package (for lack of a better word). Using the Chain Class, you could probably get the desired functionality.
var parent = (function () {
var construct = function () {
};
construct.prototype = {
constructor: construct,
destroy: function () {
console.log('parent destruction');
}
}
return construct;
})();
var child = (function (parent) {
var construct = function () {
};
construct.prototype = Object.create(parent.prototype);
construct.prototype.constructor = construct;
construct.prototype.destroy = function () {
parent.prototype.destroy.call(this); // calling parent, too
console.log('child destruction');
};
return construct;
})(parent);
child_instance = new child();
child_instance.destroy();
I would prefer a way where I don't assign Derived = chainify() so that the api would be the same as you had in your question but as of right now this is the best way I can get it to work. It works by replacing each method of the object with a method that calls the replaced method and travels up the parent chain calling their methods along the way.
function chainify() {
return function () {
var property;
for (property in this) {
if (typeof this[property] === "function") {
this[property] = chain(this[property], property);
}
}
function chain(method, method_name) {
return function() {
method();
var current = this;
while (current = current.parent) {
if (current.hasOwnProperty(method_name)) {
current[method_name].apply(this, arguments);
}
}
};
}
}
}
var somelib = function() { };
somelib.inherit = function (derive, base) {
derive.prototype = new base;
derive.prototype.parent = base.prototype;
};
var Base = function() { };
Base.prototype.foo = function() {
console.log("base foo");
};
var Derived = chainify();
somelib.inherit(Derived, Base);
Derived.prototype.foo = function() {
console.log("derived foo");
};
d = new Derived();
d.foo();

JavaScript: Public methods and prototypes

I'm not entirely sure how to implement OOP concepts in JS.
I have a class which is entirely declared in its constructor:
function AjaxList(settings)
{
// all these vars are of dubious necessity... could probably just use `settings` directly
var _jq_choice_selector = settings['choice_selector'];
var _jq_chosen_list = settings['chosen_list'];
var _cb_onRefresh = settings['on_refresh'];
var _url_all_choices = settings['url_choices'];
var _url_chosen = settings['url_chosen'];
var _url_delete_format = settings['url_delete_format'];
var jq_choice_selector_form = _jq_choice_selector.closest("form");
if (DEBUG && jq_choice_selector_form.length != 1)
{
throw("There was an error selecting the form for the choice selector.");
}
function refresh()
{
_updateChoicesSelector();
_updateChosenList();
_cb_onRefresh();
};
AjaxList.prototype.refresh = refresh; // will this be called on all AjaxLists, or just the instance used to call it?
// AjaxList.refresh = refresh; // will this be called on all AjaxLists, or just the instance used to call it?
// ...
}
There are multiple instances of AjaxList. When I call refresh() on one of them, I want only that one list to refresh itself. In the following instance:
term_list = AjaxList(settings);
term_list.refresh();
The refresh() call seems to make all the AjaxLists refresh themselves. What is the correct way to do this?
I'm using jQuery, if it makes any difference.
You should not redefine the prototype function in the constructor.
If you want to create a privileged function use this.methodname = ... from the constructor.
function AjaxList() {
var privateVar = 0;
function privateFunction() {
//...
}
//create a refresh function just for this instance of the AjaxList
this.refresh = function() {
//privileged function, it can access the 'privateVar & privateFunction'
privateVar++;
}
}
//public functions that don't need access to the private variables/functions
AjaxList.prototype.publicFunction=function() {
};
Also if you want to create a proper object, you need to change
term_list = AjaxList(settings);
to
term_list = new AjaxList(settings);
AjaxList = function(settings) {
this._jq_choice_selector = settings["choice_selector"];
this._jq_chosen_list = settings["chosen_list"];
this._cb_onRefresh = settings["on_refresh"];
this._url_all_choices = settings["url_choices"];
this._url_chosen = settings["url_chosen"];
this._url_delete_format = settings["url_delete_format"];
this.jq_choice_selector_form = _jq_choice_selector.closest("form");
if (DEBUG && jq_choice_selector_form.length != 1) {
throw "There was an error selecting the form for the choice selector.";
}
};
AjaxList.prototype = {
_updateChoicesSelector: function() { },
_updateChosenList: function() { },
_cb_onRefresh: function() { },
refresh: function() {
this._updateChoicesSelector();
this._updateChosenList();
this._cb_onRefresh();
}
};
Given that structure, you should be able to call:
var ajaxList = new AjaxList(settings);
ajaxList.refresh(); // etc.
I'm using jQuery, if it makes any
difference.
No it doesn't. See my answer here: What's the difference between Javascript, Jquery and Ajax?
I have a class which is entirely
declared in its constructor
There are no classes in Javascript. Forget them. You really need to learn some of the basics of this language in order to use them. It's not Java, even though it looks similar.
If you have a Constructor Function it will create an instance. The shared methods will be in the prototype chain, and only instance specific data goes right into the function with the this keyword.
So the basic concept of an object would look like this:
// constructor of an instance
function MyObject( param1, param2 ) {
this.param1 = param1;
this.param2 = param2;
this.param3 = 32;
return this; // [optional]
}
// Public methods can be called by any instance.
// Instances share their prototype object.
// The this keyword always points to the current
// instance that calls the method.
MyObject.prototype.sum = function() {
return this.param1 + this.param2 + this.param3;
}
// refresh should be a shared method, since it
// does the same thing on every instance
MyObject.prototype.refresh = function() {
// do the refresh
// ...
}
The power of this concept is that there is only one refresh function in memory. And it can deal with any instance. In addition, if another object inherits from MyObject the refresh function will be inherited. But in the memory there will be still one shared refresh function. And it can deal with any of the parent or child instances.

Categories