Private instance members

W

Will

Is it possible to have private instance members in a javascript class?

function myObject() {
var private = 1;

this.getPrivate = function() {
return private;
}

this.incrementPrivate = function() {
private += 1;
}
}

var a = new myObject();
var b = new myObject();
a.incrementPrivate();

When I test the example above, calling b.getPrivate() returns 2, so it
appears that private members can only be static? I know that it is
possible to use "this.private" to achieve the intended functionality
with a public member but would prefer to make the variable "private"
inaccessible to code outside the class.
 
M

Martin Honnen

Will said:
Is it possible to have private instance members in a javascript class?

function myObject() {
var private = 1;

this.getPrivate = function() {
return private;
}

this.incrementPrivate = function() {
private += 1;
}
}

var a = new myObject();
var b = new myObject();
a.incrementPrivate();

When I test the example above, calling b.getPrivate() returns 2, so it
appears that private members can only be static? I know that it is
possible to use "this.private" to achieve the intended functionality
with a public member but would prefer to make the variable "private"
inaccessible to code outside the class.

Which browser are you using?
private is a reserved word I think therefore Netscape gives an error and
shouldn't yield a result at all.
And if I try

function myObject() {
var private = 1;

this.getPrivate = function() {
return private;
}

this.incrementPrivate = function() {
private += 1;
}
}

var a = new myObject();
var b = new myObject();
a.incrementPrivate();
alert(b.getPrivate())

with IE6 it alerts 1.
 
D

Douglas Crockford

function myObject() {
var private = 1;

this.getPrivate = function() {
return private;
}

this.incrementPrivate = function() {
private += 1;
}
}

var a = new myObject();
var b = new myObject();
a.incrementPrivate();

When I test the example above, calling b.getPrivate() returns 2, so it
appears that private members can only be static? I know that it is
possible to use "this.private" to achieve the intended functionality
with a public member but would prefer to make the variable "private"
inaccessible to code outside the class.

I ran it through JSLINT and it found that you are misusing 'private', a
reserved word.

http://www.crockford.com/javascript/lint.html
 
W

Will

Sorry for the confusion. The previous example was thrown together for
demonstration purposes and I should have remembered about "private"
being a reserved word.

The problem actually relates to private instance variables with a
prototyped class. For example:

function myObject() {
var i = 1;
this.ret = function() {return i;}
this.increment = function() {i += 1;}
}

myObject2.prototype = new myObject();
function myObject2() {}

var a = new myObject2();
var b = new myObject2();
a.increment();
alert(b.ret())

In this example,b.ret() returns 2 where I would expect 1. It appears
as though both objects "a" and "b" share an instance of the prototyped
class "myObject()", because the methods of each object alter the value
of the private variable for both.

I find this behaviour a bit odd and wonder if there is either
something I am missing or a workaround to enable the two objects to
maintain the variable "i" independently of one another whilst keeping
"i" as a private variable.
 
M

Martin Honnen

Will said:
Sorry for the confusion. The previous example was thrown together for
demonstration purposes and I should have remembered about "private"
being a reserved word.

The problem actually relates to private instance variables with a
prototyped class. For example:

function myObject() {
var i = 1;
this.ret = function() {return i;}
this.increment = function() {i += 1;}
}

myObject2.prototype = new myObject();
function myObject2() {}

var a = new myObject2();
var b = new myObject2();
a.increment();
alert(b.ret())

In this example,b.ret() returns 2 where I would expect 1. It appears
as though both objects "a" and "b" share an instance of the prototyped
class "myObject()", because the methods of each object alter the value
of the private variable for both.

I find this behaviour a bit odd and wonder if there is either
something I am missing or a workaround to enable the two objects to
maintain the variable "i" independently of one another whilst keeping
"i" as a private variable.

The beahviour is not odd, and your explanation is quite right, the two
objects share an "instance of myObject" as their prototype, that is how
prototyping works, an object is created and serves as the prototype.
Whoever has sold this approach of "private instance members" should have
told you that it breaks with prototypes being introduced.
 
R

Richard Cornford

Whoever has sold this approach of "private instance members"
should have told you that it breaks with prototypes being
introduced.

As Douglas Crockford appears to be responsible for inventing the
technique for emulating private instance members in JavaScript (though I
can't see that as "selling") it is probably not surprising that he has
also published pages on alternative approaches to inheritance, some of
which would address this problem.

As the emulation of private instance members is achieved by forming a
closure, in which the private members are stored, by assigning inner
functions of the constructor to public members of the object instance,
the technique results in each object instance being associated with a
closure. Assigning an super class object instance to the prototype
results in only one closure being associated with all instances of the
subclass, but the subclass instances do not each have a closure of their
own to hold any private instance members that they may want. Attaching a
closure to the prototype is an action that can be exploited as one of
the methods of emulating private static members (the other (and perhaps
preferable) method being to associate a closure with the class
constructor).

For instances of a class to inherit private instance member
functionality from a superclass they would have to explicitly create the
same closure as the superclass, which could be achieved by using the
Function.prototype.apply or call methods to apply the superclass
constructor to the - this - object (probably within the subclass
constructor).

Richard.
 
M

Martin Honnen

Richard said:
For instances of a class to inherit private instance member
functionality from a superclass they would have to explicitly create the
same closure as the superclass, which could be achieved by using the
Function.prototype.apply or call methods to apply the superclass
constructor to the - this - object (probably within the subclass
constructor).

Sure, but apply/call only made it into IE5.5/JScript 5.5 and are not
supported in earlier JScript versions so in my view can't be relied on
currently on Web pages.
 
R

Richard Cornford

Sure, but apply/call only made it into IE5.5/JScript 5.5 and
are not supported in earlier JScript versions so in my view
can't be relied on currently on Web pages.

True, they are missing from IE 4 & 5.0, but they can each be emulated
when absent, and that addresses web page reliability issues (obviously
at the cost of maybe 20 extra lines of code).

On the other hand I have not seen much need for inheritance in a web
page environment, they are just not that complicated. Where I do see
inheritance being a significant consideration is with the implementation
of business logic in an ASP/IIS environment. But then the JScript
version is known so reliability is not an issue.

Richard.
 
T

Thomas 'PointedEars' Lahn

Will said:
Is it possible to have private instance members in a javascript class?

No, and unless you are talking about JavaScript 2.0 there are no classes
in JavaScript. The below declares and defines a constructor function
for a prototype object and therefore that object itself.
function myObject() {
var private = 1;

this.getPrivate = function() {
return private;
}

this.incrementPrivate = function() {
private += 1;
}
}

var a = new myObject();
var b = new myObject();
a.incrementPrivate();

The `new' operator creates a new object based on the prototype
object (inheriting its properties) and returns a reference to
that object which you assign to variables here, making their
identifiers object references on which the lookup operator `.'
can be applied.

Since in prototype-based languages like JavaScript 1.x every
object is an `instance', it is better to avoid that term there
to avoid confusion.

See
http://devedge.netscape.com/library/manuals/2000/javascript/1.5/guide/obj2.html#1008342


PointedEars
 
D

Douglas Crockford

Is it possible to have private instance members in a javascript class?
No, and unless you are talking about JavaScript 2.0 there are no classes
in JavaScript. The below declares and defines a constructor function
for a prototype object and therefore that object itself.

Yes, actually. The problem with the example below is that it misuses 'private',
a reserved word unfortunately. If you replaced it with a non-reserved word, then
it would act as a private instance variable that can only be access through the
priviledged functions.

See http://www.crockford.com/javascript/private.html
 
T

Thomas 'PointedEars' Lahn

Will said:
Please to report that I have now found the answer, thanks to this
excellent article:

You are wrong.

The information provided in this document is awfully wrong, most
certainly based on a lack of knowledge about prototype-based languages
in general and especially JavaScript 1.x. As for example:
[...]
Data Members

Note: Data members are variables (including object references) and
functions.

Within an object there are two types of data members supported by
JavaScript. Public and private. Public data members are those
properties that we assign to the this object within the constructor.

There is no distinction between private and public properties in
JavaScript 1.x and where a property is defined does not change its
access restrictions because there are simply *none*.

function Foo()
{
this.x = 42;
this.blurb = function() { return false; };
}

var b = new Foo();
b.y = 23;
b.haha = function() { return true; };
Foo.x = -1;
alert(x);
alert(y);
alert(Foo.x);
alert(Foo.blurb());
alert(b.blurb());
alert(b.haha());


PointedEars
 
T

Thomas 'PointedEars' Lahn

Douglas said:
[...] The problem with the example below is that it misuses 'private',
a reserved word unfortunately. If you replaced it with a non-reserved word, then
it would act as a private instance variable that can only be access through the
s/as/like/

priviledged functions.

ACK. Although understandable, I find that
way of coding somehow strange, though.
function myObject() {
var private = 1;
[...]

PointedEars
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top