tags:

views:

422

answers:

3
// base function
function Man(name) {
  // private property
  var lover = "simron";
  // public property
  this.wife = "rocy";
  // privileged method
  this.getLover = function(){return lover};
  // public method
  Man.prototype.getWife = function(){return this.wife;};
}

// child function
function Indian(){
  var lover = "jothika"; 
  this.wife = "kamala";
}

Indian.prototype = aMan;
var aMan = new Man("raja");
oneIndian = new Indian();
oneIndian.getLover();

I got answer as "simron" but I expect "jothika".

How my understanding is wrong?

Thanks for any help.

+2  A: 

The getLover property on the instance refers to the closure you defined within the Man constructor. The lover local variable inside Man is the one in-scope for that function. The lover variable you declared inside Indian has nothing whatsoever to do with the one declared inside Man, no more than local variables declared inside other functions do.

For Indian to manipulate the private lover variable inside Man, you would have to give Indian some access to it via an accessor function -- but then everything would be able to change it via that same accessor function.

T.J. Crowder
@ T.J.CrowderThe fucntion inside Manthis.getLover = function(){return lover};is it not accessor function you mention?
rajakvk
It's *an* accessor (a *getter*), but for `Indian` to modify `Man`'s copy of `lover`, `Man` would have to provide a *setter* as well.
T.J. Crowder
@T.J.Crowder But in my case, I don't want to modify anything; just want to get.
rajakvk
You want to modify it from `Indian`, apparently! :-)
T.J. Crowder
+2  A: 

First of all your code doesn't work at all and it's wrong.
Here's the code that works:

// base function
function Man(name) {
  // private property
  var lover = "simron";
  // public property
  this.wife = "rocy";
  // privileged method
  this.getLover = function(){return lover};
  // public method
  Man.prototype.getWife = function(){return this.wife;};
}

// child function
function Indian(){
  var lover = "jothika"; 
  this.wife = "kamala";
  this.getLover = function(){return lover};
}

Indian.prototype = new Man();
Indian.prototype.constructor = Indian;

var oneIndian = new Indian();
document.write(oneIndian.getLover());

aMan didn't exist until you declared it.
Also you should have set the ctor to Indian.
And at last, getLover is a closure that refers to Man and not to Indian.
Declaring it again refers it to the right scope.
See here and here for further details and improvements of your code.

the_drow
A note for the OP: Each instance of `Man` and `Indian` will get its **own** copy of those functions, which can be a memory consumption issue. If you have three instances of `Man`, there are three copies of the `getLover` function in memory.
T.J. Crowder
I didn't code this to be perfect. I just wanted to show him whats wrong.+1 For the comment
the_drow
instead of this.getLover = function(){return lover};below will do. Am i right @ T.J.CrowderMan.prototype = { getLover: function(){return lover;}}
rajakvk
@ the_drow If I have to define getLover in Indian also then what is purpose of inheritence. Can't I use parent class function to access child class's property?
rajakvk
I didn't inherit properly if I recall correctly, just read the links I gave you.
the_drow
`getWife()` should be assigned outside of the constructor: doing it inside totally defeats the purpose of assigning it to the prototype as you'll still create a new function object for each instance
Christoph
A: 

My advice: get rid of this whole priviledged method crap and don't try to shoehorn concepts from one language into another.

For performance reasons, methods should reside in the prototype. Otherwise, a new function object (which forms a closure over the constructor's local vaiables) has to be created for each instance, which is highly inefficient.

If you want to hide properties (ie 'private' fields), add a prefix like _private_ to their name and tell the programmer not to do stupid things.

Christoph
Ever heard about Murphy's law? If it can be used incorrectly, it will!"Edward Murphy Jr. was a US Air Force engineer. He coined this infamous law after discovering a technician had systematically connected a whole row of devices upside down. Symmetric connectors permitted this avoidable mistake; afterward, he chose a different connector design." - from the book Code Craft.
Pablo Cabrera
@Pablo: Ever heard of square pegs in round holes or respecting the programmer? There just is no way to implement access protection mechanisms efficiently in JavaScript; so you can either penalize everyone or just make it clear whenever the programmer does something at his own risk; my vote is for the latter
Christoph
@Christoph: You *can* implement them efficiently in JavaScript, just not using the mechanisms in this thread (which as you know cause large per-instance overhead). For code libraries, I see a justification for doing it. For application code, though, I typically don't.
T.J. Crowder
@T.J.: How? All implementations I know either carry the large per-instance overhead or introduce side effects more severe than the original problem (eg having destructors which have to be called manually)
Christoph
@T.J.: did you mean something like this: http://stackoverflow.com/questions/483213/javascript-private-member-on-prototype/483294#483294 (as you can see, I obviously know about such implementations;))
Christoph
You could have small functions attached to each instance that delegates to a hidden common function that actually does the job... is not that much of an overhead per instance since the delegating function is small.
Pablo Cabrera
@Christoph: For private *methods*, there are efficient ways that don't have either problem. For private *data*, I'm with you, it's either unacceptable (to me!) per-instance overhead or a destructor to release private data associated with the instance.
T.J. Crowder
@T.J.: my answer was a rant about priviledged methods, so obviously it was about instance-specific /data/; sharing static values (this includes the 'private' methods you mentioned) is trivial: just use a global and wrap the whole thing (including method definitions) in a self-executing function for namespacing
Christoph
@Pablo: you'll still have a `O(method_count * instance_count)` overhead; if you create enough instances, it might well be significant
Christoph
@Christoph: Woudn't ou have a (var_count * instance_count) anyway? What is the problem with a few more small "vars" (since functions are objects aswell in JS)? It's not that you gonna add hundreds of methods per instance...
Pablo Cabrera