Operator Overloading Javascript? (def.js) [duplicate] - javascript

Today I saw a JavaScript syntax (when invoking a function) that is unfamiliar to me. It was like:
def('Person') ({
init: function(name) {this.name=name;}
,speak: function(text) {alert(text || 'Hi, my name is ' + this.name);}
});
, and
def('Ninja') << Person ({
kick: function() {this.speak('I kick u!');}
});
1: What happens with the object within the parentheses in the first example? It is handled by the def function somehow, but I don't understand what is going on here (see the def function below). Where does the object go?
2: About the same thing again, but a use of the << operator that I never seen (I think!). What's that all about?
The code is from http://gist.github.com/474994, where Joe Dalton has made a small JavaScript-OO-inheritance thing (it is apparently a fork of someone else's work, but quite thoroughly rewritten, as it seems). Maybe you want to check it out there for the stuff referenced by the def function, which I give you here:
function def(klassName, context) {
context || (context = global);
// Create class on given context (defaults to global object)
var Klass =
context[klassName] = function Klass() {
// Called as a constructor
if (this != context) {
// Allow the init method to return a different class/object
return this.init && this.init.apply(this, arguments);
}
// Called as a method
// defer setup of superclass and plugins
deferred._super = Klass;
deferred._plugins = arguments[0] || { };
};
// Add static helper method
Klass.addPlugins = addPlugins;
// Called as function when not
// inheriting from a superclass
deferred = function(plugins) {
return Klass.addPlugins(plugins);
};
// valueOf is called to set up
// inheritance from a superclass
deferred.valueOf = function() {
var Superclass = deferred._super;
if (!Superclass)
return Klass;
Subclass.prototype = Superclass.prototype;
Klass.prototype = new Subclass;
Klass.superclass = Superclass;
Klass.prototype.constructor = Klass;
return Klass.addPlugins(deferred._plugins);
};
return deferred;
}

1: The call def('Person') returns a function, which is called with the object as parameter. It's the same principle as:
function x() {
return function(y) { alert(y); }
}
x()('Hello world!');
2: The << operator is the left shift operator. It shifts an integer value a specific number of bits to the left. I haven't found any reference for any other use for it, and there is no operator overloading in Javascript, so I can't make any sense out of using it on a function. So far it looks like a typo to me.
Edit:
As Tim explained, the shift operator is just used to induce a call to the valueOf method. It works like an overload of all operators, taking over the original purpose and doing something completely different.

Wow, it was convoluted enough for my tiny brain to understand, but I feel a lot better now knowing exactly how it works :) Thanks to #Tim for pointing out the valueOf() trick.
The general case of creating a "class" using:
def ("ClassName") ({
init: function() { .. },
foo: function() { .. }
});
is trivial, as the first call to def returns a function that accepts an object, and copies the properties of the passed in object, to the prototype of ClassName.
The more interesting case of using << to subclass relies on the evaluation order of the expression, as well as the attempted coercing of any object to a value by the implicit call to valueOf(). The underlying trick is basically a shared variable that records the super class and the properties to be applied to it. The expression,
def("ClassName") << ParentClass({ .. })
will be evaluated as follows:
def("ClassName") is called, and creates a global object ClassName and returns its constructor function. Let's call this returned object - initializeMeLater.
ParentClass(..) is called which stores the reference to ParentClass, and the passed in object/properties in a shared variable.
initializeMeLater.valueOf() is called, which gets the reference to the parent class, and the properties from that shared variable, and sets up the prototypes.
valueOf is called on the return value from step 2 which is useless and has no effect, as we have already setup the superclass relationship in step 3.
The code is trying to emulate Ruby syntax for creating subclasses which goes like:
class Child < Parent
def someMethod
...
end
end

Related

What is it called when a function behaves like a class but doesn't use the class keyword, nor "new" keyword (in Javascript)?

I looked through the suggested links but can't seem to find the term for a function that acts like a class (is it a constructor function? doesn't have that keyword either!) but doesn't use the new keyword, nor class.
I've used both this example's pattern and the class pattern in my code but realized I don't know how to describe the former.
I think this is in part because I learned JS recently, have seen class thrown around a lot, yet looking through my notes of not-ES5,6,7,2018,2020 etc. can't seem to find what var aCounter = counterFunction() is called for the life of me.
I know what the result of what i'm doing is, how to work it, etc. but why no constructor(), no new, no class, no etc.prototype.etc pattern? I know i'm creating an object, calling a method existing Within the object, etc. I believe i'm beginning to ramble.
Lo, an example
const counterFunction = () => {
let val = 0
return {
increment() { val++ },
getVal() { return val }
}
}
which is || can be instantiated (?) like so:
let aCounter = counterFunction() // where i'm getting tripped up
and works like
aCounter.increment() // 1
aCounter.increment() // 2
aCounter.getVal() // 2
I know this is rambling, but help! I think it will make things click more inside once this lexical puzzle piece is put into position!
That is just a function that returns an object literal, which does not act like a class (doesn't have a prototype, and as you pointed out, does not use new, etc).
The functions that are set as the properties of this object (which you store in aCounter) seem to act like class methods because they keep the reference to the variable val alive, but this is not because val is in any way associated with the actual object.
Instead, those functions are closures that keep the reference to the variable alive for as long as the functions themselves are alive.
So to answer your question, what you have described doesn't have any name in particular. It's just a function that returns an object.
Edit:
You asked why there is no constructor() or related syntax in this pattern. Object literals in JavaScript are just mappings of names and values:
const x = { a: 3, b: "hello" };
You do not need a constructor for this, and there is no prototype because it was not instantiated using a constructor. On the other hand, classes and constructor functions are templates for objects that will be created later, and those objects do have a prototype and a constructor because the template contains logic that initializes the object.
class A
{
constructor()
{
this.a = new Date();
this.b = this.a.toString(); // you cannot do this in an object literal
}
}
const x = new A();
Question:
What is it called when a function behaves like a class but doesn't use the class keyword, nor “new” keyword (in Javascript)?
Answer:
It's called a "factory function".
Factory functions usually return a object of a consistent type but are not instances of the factory function itself. Returned objects would rarely inherit from the factory function's prototype property, and calling the factory function does not require new before the function being called.
What you showed there is nothing special. It is just a normal function that has a closure.
Though, you can call it as a type of design pattern.
It looks similar to Revealing Module Pattern where you can separate public property and private property.
Below is an example (not a good one tho):
var counter = function(){
var privateCount = 0;
var privateHistory = [];
return {
getVal: function(){
return privateCount;
},
increment: function(){
privateCount++;
privateHistory.push('+');
return this.getVal();
},
decrement: function(){
privateCount--;
privateHistory.push('-');
return this.getVal();
},
publicHistory: function(){
return privateHistory;
}
}
}
var aCounter = counter();
console.log(aCounter.increment());
console.log(aCounter.decrement());
console.log(aCounter.publicHistory());
Here, you can't directly manipulate the private variables that I don't expose to you.
You can only manipulate those private variables only if I expose the function to you. In this case, the .increment() and .decrement() function.
As you can see, there is no class, no prototype, no constructor.
I can see how you may get tripped up, let's go through your code and explore what's going on:
const counterFunction = () => {
let val = 0
return {
increment() { val++ },
getVal() { return val }
}
}
At this point counterFunction is a variable that points to a function, it's essentially a function name. The ()=>{...} is the function body or function definition and within it the return statement shows that it returns an unnamed object with two property methods.
let aCounter = counterFunction() // where i'm getting tripped up
This is calling your previously defined function, which again returns the object with two methods and assigns it to the variable aCounter. If you did the same thing again for a variable called bCounter they would hold two independent objects.
and works like
aCounter.increment() // 1
aCounter.increment() // 2
aCounter.getVal() // 2
Because the method inside the object refers to a variable outside the scope of the object, but within the function body, a closure is created so that the state of val may be retained. Because the variable is in use, the browser's cleanup process skips over it, so the function is still kept in memory, I believe until the object is destroyed and the function's variable is no longer used.

Can someone please explain Douglas Crockford's uber method?

I went through the following example from here
But I am not able to understand from LINE 1:
Function.method('inherits', function(parent){
this.prototype = new parent();
var d = {},
p = this.prototype;
this.prototype.constructor = parent;
this.method('uber', function uber(name){ //LINE 1
if(!(name in d)){
d[name] = 0;
}
var f, r, t = d[name], v = parent.prototype;
if(t){
while(t){
v = v.constructor.prototype;
t -= 1;
}
f = v[name];
} else {
f = p[name];
if(f == this[name]){
f = v[name];
}
}
d[name] +=1;
r = f.apply(this, Array.prototype.slice.apply(arguments, [1]));
d[name] -= 1;
return r;
});
return this;
});
I went through the following example of Douglas Crockford's uber method
Oh, you poor lost soul. Notice that this function had its origin in 2002 (or earlier), when the language standard version was still ES3. This year, we will see ES9!
You can check the web archive to see the function slowly evolving to deal with all the edge cases that were discovered, and Crockford trying to fix them. (Notice that it still fails horribly if one of the involved methods throws an exception).
Needless to say, this is totally outdated. And borked.
Can someone please explain it?
I'll try to take a shot. Lets take the following code:
function A() { }
A.prototype.exampleMethod = function() {
console.log("top");
return "result";
};
function B() { }
B.inherits(A);
B.prototype.exampleMethod = function() {
console.log("parent");
return this.uber("exampleMethod");
};
function C() {
this.exampleMethod = function() {
console.log("instance");
return this.uber("exampleMethod");
}
}
C.inherits(B);
C.prototype.exampleMethod = function() {
console.log("prototype");
return this.uber("exampleMethod");
};
var x = new C();
console.log(x.exampleMethod());
This does should log instance, prototype, parent, top, result - as one might have expected from a "super" call. How do these this.uber("exampleMethod") invocations - the same method called with the same arguments on the same instance - achieve this? Horrible jugglery and trickery.
We see that this.uber always calls the method that C.inherits(B) had created. B.prototype.uber is irrelevant. All calls will use the same d object (referenced by closure), which stores the recursion depth per method name. p is C.prototype, and v is B.prototype.
The first call is from the instance method (created in the constructor). d.exampleMethod is still 0 (or was just initialised to it as it didn't exist before), and we go to the else branch to select the next method to call. Here it checks p[name] == this[name], i.e. C.prototype.exampleMethod == x.exampleMethod, which is false when the instance (this/x) has an own (instance) method. So it selects the method from p, not from v, to call next. It increments the recursion count and calls it on the instance.
The second call is from the C.prototype method. If this was the first call (as usual when having only prototype methods), d.exampleMethod would be 0. Again we'd go to the else branch, but when there is no instance method we would have the comparison evaluate to true and would select v[name] to call, i.e. the parent method we inherited. It would increment the recursion count and call the selected method.
The third call would be from the B.prototype method, and d.exampleMethod would be 1. This actually already happens in the second call, because Crockford forgot to account for the instance method here. Anyway, it now goes to the if branch and goes up the prototype chain from v, assuming that the .constructor property is properly set up everywhere (inherits did it). It does so the for the stored number of times, and then selects the next method to call from the respective object - A.prototype.exampleMethod in our case.
The counting must be per-methodname, as one could attempt to call a different method from any of the invoked super methods.
At least that must have been the idea, as obviously the counting is totally off in case there is an instance method. Or when there are objects in there prototype chain that don't own the respective method - maybe also that was a case that Crockford attempted but failed to deal with.
If you're trying to understand how classes could be implemented using ES5 and how to implement inheritance of classes, the code example from Douglas Crockford is kinda outdated and just a pure mess.
This makes it extremly difficult for beginners to understand it. (Also his explanation lacks a fair amount of detail and is not helping at all)
In my opinion a much better example of how to implement a class pattern with ES5 would be: http://arjanvandergaag.nl/blog/javascript-class-pattern.html
But netherless, lets go trough it step by step:
// He extended the "prototype" of the Function object to have some syntactic sugar
// for extending prototypes with new methods (a method called 'method').
// This line extends the prototype of the Function object by a method called 'inherits' using the syntactic sugar method mentioned above.
Function.method('inherits', function(parent){
/** 'this' is a reference to the Function the 'inherits' method is called
* on, for example lets asume you defined a function called 'Apple'
* and call the method 'inherits' on it, 'this' would be a reference of 'Apple'-Function object.
**/
/**
* Hes extending the prototype of the base function by the prototype of
* the 'parent' function (the only argument the 'inherits' method takes),
* by creating a new instance of it.
**/
this.prototype = new parent();
// BAD VARIABLE NAMING!!!
var d = {}, // variable to create a dictionary for faster lookup later on.
p = this.prototype; // save the prototype of the base function into variable with a short name
this.prototype.constructor = parent; // set the constructor of the base function to be the parent.
/**
* Extend the base function's prototype by a method called 'uber',
* it will nearly the same function as the 'super' keyword in OO-languages,
* but only to call methods of the parent class.
**/
this.method('uber', function uber(name){
if(!(name in d)){
// if the value name doesn't exist in the dictionary
d[name] = 0; // set the key to the value of name and the value to 0
}
// BAD VARIABLE NAMING AGAIN!!!
var f, r, t = d[name], v = parent.prototype;
// f is used to store the method to call later on.
// t is the value of the key inside the 'd' dictionary which indicates the depth to go up the prototype tree
// v is the parent functions prototype
// r is the result the method 'f' yields later on.
// check if the attribute 'name' exists in the dicionary.
// because if it doesn't exist t will be 0 which resolves to false.
if(t){
// the loop is used to walk the tree prototype tree until the implementation with the depth of t is found.
while(t){
v = v.constructor.prototype;
t -= 1;
}
f = v[name]; // set f to the method name of the t-th parent protoype
} else {
// if the attibute 'name' doesn't exist inside the dictionary
f = p[name]; // use the method 'name' of the base class prototype.
if(f == this[name]){
// if the method 'name' is a member of the base class
f = v[name]; // use the method 'name' of the parent prototype instead.
}
}
// increment the corresponding dictionary value for the depth of the 'uber' call.
d[name] +=1;
// call the method saved to 'f' in context of the base class and apply the 'arguments' array to it and save the result to 'r'.
r = f.apply(this, Array.prototype.slice.apply(arguments, [1]));
// decrement the corresponding dictionary value for the depth of the 'uber' call.
d[name] -= 1;
// return the result
return r;
});
return this;
});
Hope this explanation kinda helps you, but i might be wrong on some lines because the code is such a weird implementation and is far off from easily readable.

Differences between "this" in JavaScript and ActionScript

My background is heavy in JavaScript. I have a very advanced understanding of both ES5 and ES6. At work I was recently assigned a project involving an older flash application, which uses AS2. It is my understanding that ActionScript is very similar to ES5, but with classes and optional strict typing (akin to TypeScript and Flow), as well as a few other classic OO features. It is fairly straightforward so far, but I'm having trouble understanding how this and references work in ActionScript.
This is my understanding for JavaScript. this in a function can reference:
A bound variable, if using Function.bind() (as well as Function.call() and Function.apply()), which cannot be changed in the bound function, for example:
function func() {
return this.number;
}
var bound = func.bind({ number: 2 });
console.log(bound()); // 2
An object, if the function is called as a method on that object, for example:
function func() {
return this.number;
}
var obj = { number: 2, func: func };
console.log(obj.func()); // 2
An instance of a class, if that function is defined on the prototype of that class, for example:
function Class() {
this.number = 2;
}
Class.prototype.func = function func() {
return this.number;
}
console.log(new Class().func()); // 2
The global object, if the function is called without any kind of binding or object or instance attached to it, for example:
var number = 2;
function func() {
return this.number;
}
console.log(func()); // 2
In ActionScript things seem to be a bit different. For one thing, you can access class members without this if you are doing it within a method of that class, similar to languages like C# and Java:
class MyClass {
private var number:Number = 2;
public function func():Number {
return number;
}
}
trace(new MyClass().func()); // 2
Also, the ActionScript standard library doesn't seem to have a Function.bind() method, though it does have Function.apply() and Function.call() which seem to work just like the JavaScript variations: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/2/help.html?content=00001072.html#265677. There also don't seem to be prototypes, which makes sense because classes are more abstract syntactic structures rather than functions (just like C#/Java) based on my understanding.
So my question is, excluding the lack of Function.bind() and Function.prototype, are the rules the same between ActionScript and JavaScript?
In addition, what happens if I do this:
class SomeClip extends MovieClip {
private var childClip:MovieClip;
private var number:Number = 2;
public function SomeClip() {
this.onLoad = function() {
// SomeClip onLoad hander, `this` will be the SomeClip instance
childClip._visible = true; // How is childClip resolved here?
childClip.onRelease = function() {
// childClip onRelease handler, `this` will be childClip
trace(number); // How is number resolved here?
};
};
}
}
Basically, if you access a member without this in an event handler, or some other loose function that is not a method of the class, what happens? I would guess that in the first case, it would resolve to this.childClip and work as one would expect, but in the second case, the resolution would fail because the onRelease handler's closure won't contain a reference to the SomeClip instance.
I see the comments that have been written so far are more focused on JS, so I'll try my best to answer from an ActionScript perspective.
In the world of AS2/AS3, functions that are defined as methods on a class have their this value bound to the class. This is typical of many higher-level languages with modern classes, such as Java, Haxe, etc. As such, in ActionScript you'll rarely find the need to use the this keyword other than cases where a variable name might be shadowed by a function argument:
public function Point(x:Number = 0, y:Number = 0)
{
// A rare but necessary use-case of "this" in AS2/AS3
this.x = x;
this.y = y;
}
On the other hand, if the function you provide is anonymous as in the example you wrote, the behavior depends on whether or not you prepend this:
childClip.onRelease = function() {
trace(number);
};
In this case ActionScript is able to determine number is a member of the class, and will print 2 like you expected since. This is because the interpreter looks for the next closest thing in the stack. In other words, you were ambiguous by excluding this so it knows it needs to perform a lookup.
However if you were to trace(this.number) instead, you would find that you get an undefined (and possibly even an error). This is because this is not a member variable on the class, and now points to a "global object" similar to JS. To avoid dancing with the global object, it's common practice for ActionScript developers to define all of their listeners as class instance methods:
class MyClass extends EventDispatcher
{
private function MyClass()
{
addEventListener(Event.CHANGE, onChangeEvent);
}
private function onChangeEvent(e:Event) {
trace(this); // refers to this class, and no need for bind() like JS
}
}
Well organized AS3 code will almost never contain inline anonymous functions, since it's much easier to handle garbage collection by using explicit function references.
One last thing to note - you can expect functions that are methods of regular Objects in ActionScript to behave like JavaScript where passing them around via event listeners will result in the context of this being lost, and Flash will not do the magic lookup to locate the variable you referenced:
var obj = {
func: function () {
trace(this); // weird global object
}
};
addEventListener(Event.CHANGE, obj.func);
Hope that helps!
In AS2 functions are not bound and get "this" reference passed (evidently via Function.apply or by the object reference) in the moment of call:
function getIndex()
{
trace(this.index);
}
var A = {index:1, getIndex:getIndex};
var B = {index:2, getIndex:getIndex};
A.getIndex(); // 1
B.getIndex(); // 2
B.getIndex.apply(A); // 1
Binding methods to certain objects was called "delegating": http://help.adobe.com/en_US/AS2LCR/Flash_10.0/help.html?content=00001842.html#1001423 In a nutshell, functions are objects too and you can create special function object that has references to both method to call and "this" object to pass:
function getIndex()
{
trace(this.index);
}
function bind(method, target):Function
{
var result:Function = function()
{
// arguments.callee is always a reference
// to the current function object
arguments.callee.method.apply(arguments.callee.target);
}
result.method = method;
result.target = target;
return result;
}
var A = {index:1};
var B = {index:2};
A.getIndex = bind(getIndex, A);
B.getIndex = bind(getIndex, B);
A.getIndex(); // 1
B.getIndex(); // 2
B.getIndex.apply(A); // 2
Then, if you don't use "this" reference, once you address some variable by its name there are several contexts that are searched for such a variable in order:
local function variables
local wrapper function variables (this one is truly horrible for no one really knows where these variables exist and it is a potent memory leak)
MovieClip, that holds the function code, local variables
global variables
Play with the following code, comment some "index" variables and you'll see it:
// Global variable.
_global.index = 6;
// MovieClip local variable.
var index = 5;
function wrap():Function
{
// Wrapper function local variable.
var index = 4;
return function()
{
// Function local variable.
var index = 3;
trace(index);
}
}
wrap()();

How do I inherit a function from a base object and overwrite it in javascript

What I am trying to do is have a child object provide its own implementation for a function defined in a base object. As far as I've understood so far prototypes are the best (only!) way to go about doing this.
Note also that I am currently developing using the game engine: Turbulenz and as such I am trying to follow / stick to their style as closely as possible. In the engine "classes"/objects are defined and created in the following manner
function baseObject() { }
baseObject.prototype =
{
myMember1: 1,
myMember2: 2,
myMethod: function myMethodFn() {
return this.myMember1 + this.myMember2;
}
}
baseObject.Create = function baseObjectCreateFn
{
var o = new baseObject();
return o;
}
This would allow me to do the following
var anObject = baseObject.Create();
var someValue = anObject.myMethod(); // should return 3
What I would like to be able to do now is to create a new object that inherits all the properties of baseObject while allowing me to overwrite its myMethod function to for example subtract the two member values instead of add.
Would I be correct in saying that I will have to create another object then alter its prototype? The part thats throwing me most is that the definition of the baseObject's prototype is defined as an object literal and so I'm unsure of the syntax to overwrite one of its members, i.e. would the following be valid or not? :
function childObject() {}
childObject.prototype = baseObject.Create() // would this inherit from baseObject?
// or should it be: childObject.prototype = new baseObject();
// this is the part thats confusing me as the syntax
// doesn't quite match the original base objects prototype
// syntax and I'm unsure if that will matter
childObject.prototype.myMethod = function myMethodFn() {
return this.myMember1 - this.myMember2;
}
childObject.Create = function childObjectCreateFn
{
var o = new childObject();
return o;
}
var aChildObject = childObject.Create()
var anotherValue = aChildObject.myMethod() // would this return -1 as expected?
To summarise I'm trying to create an object that will overwrite a function that exists in a base object by inheriting the function from the base object and changing it, how do I do this? Thanks for your time.
You have it correct.
As for the syntax confusion, there is no real difference between
thing.prototype.myMethod = function () { ... }
and
thing.prototype = { myMethod: function() { ... } };
except for the fact that in the second one you are setting the prototype all at once (to an object literal), and if you do it again, you'll overwrite the prototype all at once with a new object literal. But because it is an object literal, you can't do inheritance this way (everything declared with naked braces { ... } is just an instance of Object of no special type). If you stick with the first syntax you'll always be ok.
Note that when you put:
childObject.prototype.myMethod = function myMethodFn() { ... }
The part where you put myMethodFn is actually ignored. The function is named myMethod by the fact that this is where you assigned it.
Similarly, where you have
childObject.Create = function childObjectCreateFn
you don't need childObjectCreateFn (it's ignored), and you need to put parentheses () somewhere after function or it's a syntax error.
Moving on to the reason why this works, every created object in Javascript has a prototype. When you call a method on that object, it first looks inside the object itself to see if a key corresponding to the name of the method exists. If not, it looks in the prototype object for the same thing, and if it's not there, it goes to that object's prototype, and so on, until it gets to the root Object, which has no prototype.
In this way you can override an implementation merely by naming it the same thing, but having it appear earlier in the prototype chain. That's exactly what you're doing on childObject. It retains the functionality of baseObject because you created an instance of baseObject to serve as childObject's prototype. Then you augmented childObject's prototype with a new method of the same name, but one that comes earlier in the prototype chain.

Recursively call "parent" constructors in Javascript?

I am working on a webapp that has something like a class hierarchy created through prototype-based inheritance. We're constantly adding features to a common ancestor "class" so its constructor signature is constantly expanding.
Each time we change the ancestor's signature, we'll also have to propagate the changes to thedescendants' constructors. This is obviously a maintainability problem, so I created a function that extracts the arguments for the parent from the arguments object and calls the parent using Function.apply().
The code looks like this:
BaseClass.prototype._super = function(args) {
args = Array.prototype.slice.call(args, this.constructor.length);
this.parentConstructor.apply(this, args);
};
and used like this:
function Child(child_arg1, child_arg2 /*, implicit parent args */) {
this._super(arguments);
}
(I can't use arguments.caller.arguments because the code is strict mode.
this.parentConstructor is set by the function building the class hierarchy.)
Unfortunately, this only works for one level of inheritance: for example, if A's parent class B has its own parent class C, when B calls _super, this.parentConstructor still points at B which means B will end up calling itself in an infinite loop.
If I store the parentConstructor field with the constructor Functions objects (instead of in the prototypes), I'll have to pass in the current calling function. This will make the line calling super tightly coupled to the surrounding function, which I am trying to avoid.
Thus does anyone know any better ways?
I asked a related question a couple days ago and Kamyar Nazeri's answer helped me a lot.
The way to avoid your problem is to define _super in a closure where the new constructor is defined so that it always references the correct parent object. The following pattern has worked very well for me:
var BaseClass =
{
create: function() // Basically a constructor
{
var obj = Object.create({});
obj.someProperty = "initial value based on arguments";
return obj;
};
};
var Child = (function buildChild(){
var obj = BaseClass.create("some value", "another argument")
, _super = Object.getPrototypeOf(obj);
// override BaseClass.create()
obj.create = function()
{
var obj = _super.create.apply(this, arguments);
// Child specific initializations go here
return obj;
};
return obj;
})(); // note that this gets called right away
var c = Child.create("some argument", "another thing");
console.log(BaseClass.isPrototypeOf(c)); // true
Note that for older browsers you will need to provide shims for Object.create() and Object.getPrototypeOf(). I've found this ECMAScript 5 shim to be helpful. I typically only pull out the shims that I'm using.

Categories

Resources