I am wondering can we still change the function body once it is constructed ?
var O = function(someValue){
this.hello = function(){
When you create an instance of the O object using new O("somename"); you are assigning an instance method to the newly created object. When you then assign another method of the same name to O's prototype the method is already shadowed by the instance method. So:
Object.prototype.hello // undefined
|
O.prototype.hello // alternate function
|
i.hello // original function provided in constructor
JavaScript starts at the bottom of the chain and stops when it finds a match for the name. So it stops at i.hello and never sees O.prototype.hello.
JavaScript (as of ECMAScript 5) really doesn't (as far as I am aware) give you a good way to do private variables like that that can be accessed by instance methods added after definition (either added on the instance or on the prototype). Closures get you most of the way there but if you want to be able to add methods outside of the closure that have access to closure variables you need to expose get and / or set methods that give these new methods access to the closure variables:
// Possibility #1 - marked as private member
var O = function(someValue) {
this._someValue = someValue;
};
O.prototype.hello = function() { return "hhhh"; };
var i = new O("somename");
i.hello = function() { return "aloha," + this._someValue; };
console.log(O.hello()); // hhhh
console.log(i.hello()); // aloha, somename
// Possibility #2 - factory function + closure with get and set methods
var OMaker = function(someValue) {
var realO = function() {};
realO.prototype.getSomeValue = function() { return someValue; };
realO.prototype.setSomeValue = function(newVal) { someValue = newVal; };
realO.prototype.hello = function() { return "hhhh"; };
return realO;
};
var O = OMaker("somename"),
i = new O();
i.hello = function() { return "aloha," + this.getSomeValue(); };
console.log(O.hello()); // hhhh
console.log(i.hello()); // aloha, somename
// Possibility #3 - eschew prototype inheritance and create new objects
var O = function(someValue) {
return {
getValue: function() { return someValue; },
setValue: function(newValue) { someValue = newValue; },
hello: function() { return "hhhh"; }
};
};
var i = O(); // Note the lack of the "new" keyword
i.hello = function() { return "aloha," + this.getSomeValue(); };
console.log(O.hello()); // hhhh
console.log(i.hello()); // aloha, somename
You'll really want to read bobince's great answer on OOP in JavaScript for more information on the subject.