Private instance members

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Will

    Private instance members

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

    function myObject() {
    var private = 1;

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

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

    var a = new myObject();
    var b = new myObject();
    a.incrementPriv ate();

    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.priva te" to achieve the intended functionality
    with a public member but would prefer to make the variable "private"
    inaccessible to code outside the class.
  • Martin Honnen

    #2
    Re: Private instance members



    Will wrote:
    [color=blue]
    > Is it possible to have private instance members in a javascript class?
    >
    > function myObject() {
    > var private = 1;
    >
    > this.getPrivate = function() {
    > return private;
    > }
    >
    > this.incrementP rivate = function() {
    > private += 1;
    > }
    > }
    >
    > var a = new myObject();
    > var b = new myObject();
    > a.incrementPriv ate();
    >
    > 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.priva te" to achieve the intended functionality
    > with a public member but would prefer to make the variable "private"
    > inaccessible to code outside the class.[/color]

    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.incrementP rivate = function() {
    private += 1;
    }
    }

    var a = new myObject();
    var b = new myObject();
    a.incrementPriv ate();
    alert(b.getPriv ate())

    with IE6 it alerts 1.
    --

    Martin Honnen


    Comment

    • Douglas Crockford

      #3
      Re: Private instance members

      > function myObject() {[color=blue]
      > var private = 1;
      >
      > this.getPrivate = function() {
      > return private;
      > }
      >
      > this.incrementP rivate = function() {
      > private += 1;
      > }
      > }
      >
      > var a = new myObject();
      > var b = new myObject();
      > a.incrementPriv ate();
      >
      > 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.priva te" to achieve the intended functionality
      > with a public member but would prefer to make the variable "private"
      > inaccessible to code outside the class.[/color]

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




      Comment

      • Will

        #4
        Re: Private instance members

        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.proto type = 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.

        Comment

        • Martin Honnen

          #5
          Re: Private instance members



          Will wrote:
          [color=blue]
          > 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.proto type = 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.[/color]

          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.
          --

          Martin Honnen


          Comment

          • Will

            #6
            Re: Private instance members

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



            Well worth a read.

            Comment

            • Richard Cornford

              #7
              Re: Private instance members

              "Martin Honnen" <mahotrash@yaho o.de> wrote in message
              news:3f9a4015$1 @olaf.komtel.ne t...
              <snip>[color=blue]
              >Whoever has sold this approach of "private instance members"
              >should have told you that it breaks with prototypes being
              >introduced.[/color]

              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.protot ype.apply or call methods to apply the superclass
              constructor to the - this - object (probably within the subclass
              constructor).

              Richard.


              Comment

              • Martin Honnen

                #8
                Re: Private instance members



                Richard Cornford wrote:[color=blue]
                > 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.protot ype.apply or call methods to apply the superclass
                > constructor to the - this - object (probably within the subclass
                > constructor).[/color]

                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.

                --

                Martin Honnen


                Comment

                • Richard Cornford

                  #9
                  Re: Private instance members

                  "Martin Honnen" <mahotrash@yaho o.de> wrote in message
                  news:3f9e801f$1 @olaf.komtel.ne t...
                  <snip>[color=blue][color=green]
                  >>... , which could be achieved by using the
                  >>Function.prot otype.apply or call methods to apply the
                  >>superclass constructor to the - this - object (probably
                  >>within the subclass constructor).[/color]
                  >
                  >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.[/color]

                  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.


                  Comment

                  • Thomas 'PointedEars' Lahn

                    #10
                    Re: Private instance members

                    Will wrote:[color=blue]
                    > Is it possible to have private instance members in a javascript class?[/color]

                    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.
                    [color=blue]
                    > function myObject() {
                    > var private = 1;
                    >
                    > this.getPrivate = function() {
                    > return private;
                    > }
                    >
                    > this.incrementP rivate = function() {
                    > private += 1;
                    > }
                    > }
                    >
                    > var a = new myObject();
                    > var b = new myObject();
                    > a.incrementPriv ate();[/color]

                    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



                    PointedEars

                    Comment

                    • Douglas Crockford

                      #11
                      Re: Private instance members

                      > > Is it possible to have private instance members in a javascript class?[color=blue]
                      >
                      > 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.[/color]

                      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.
                      [color=blue][color=green]
                      > > function myObject() {
                      > > var private = 1;
                      > >
                      > > this.getPrivate = function() {
                      > > return private;
                      > > }
                      > >
                      > > this.incrementP rivate = function() {
                      > > private += 1;
                      > > }
                      > > }
                      > >
                      > > var a = new myObject();
                      > > var b = new myObject();
                      > > a.incrementPriv ate();[/color][/color]

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

                      Comment

                      • Thomas 'PointedEars' Lahn

                        #12
                        Re: Private instance members

                        Will wrote:
                        [color=blue]
                        > Please to report that I have now found the answer, thanks to this
                        > excellent article:[/color]

                        You are wrong.
                        [color=blue]
                        > http://www.pbwizard.com/Articles/class_inheritance.htm
                        >
                        > Well worth a read.[/color]

                        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:
                        [color=blue]
                        > [...]
                        > 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.[/color]

                        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

                        Comment

                        • Thomas 'PointedEars' Lahn

                          #13
                          Re: Private instance members

                          Douglas Crockford wrote:[color=blue]
                          > [...] 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[/color]

                          s/as/like/
                          [color=blue]
                          > priviledged functions.[/color]

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

                          PointedEars

                          Comment

                          Working...