A while a go I wrote a post on Prototype Inheritence in Python. This time, I am somewhat going the opposite direction. That's right: Python-Style OO in Javascript.
Now, I don't think I am the first one who thought of this. In fact, prototype.js does something like this for their method extensions to DOM objects. The main idea is this: if you specify self as the first argument to a method explicitly, you will be able to use self inside of nested closures within the method without having to create a self variable manually, i.e.:
var self = this
or doing something like Function.prototype.bind, or pass the context explicitly around like the Array methods forEach, map, every, etc.
This is but a small proof-of-concept. The result is you can write a class like this:
var Man = Class(Object)({
__init__: function(self, name){
self.name = name
},
greeting: function(self, other){
setTimeout(function(){
self.say("Hello, " + other.name + ", my name is " + self.name)
}, 100)
},
say: function(self, msg){
sys.puts(msg)
}
})
Take it for a spin:
var dan = new Man('Dan')
var john = new Man('John')
dan.greeting(john)
john.say('How do?')
Output:
How do?
Hello, John, my name is Dan
The implementation of Class looks like this:
function toArray(args){
var ret = []
for (var i = 0; i < args.length; i++)
ret.push(args[i])
return ret
}
function Class(parent){
function bind(func, obj){
var ret = function(){
var args = toArray(arguments)
args.splice(0, 0, obj)
return func.apply(undefined, args)
}
return ret
}
return function(attrs){
return function(){
for (var name in attrs){
var value = attrs[name]
if (typeof(value) == 'function'){
this[name] = bind(value, this)
this[name].name = name
}else{
this[name] = value
}
}
this.__init__.apply(this, arguments)
}
}
}
Full source can be found here. I ran it in node. This could be an interesting approach to avoiding "this-hell".