199

Is there any way to make “private” variables (those defined in the constructor), available to prototype-defined methods?

TestClass = function(){
    var privateField = "hello";
    this.nonProtoHello = function(){alert(privateField)};
};
TestClass.prototype.prototypeHello = function(){alert(privateField)};

This works:

t.nonProtoHello()

But this doesn’t:

t.prototypeHello()

I’m used to defining my methods inside the constructor, but am moving away from that for a couple reasons.

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
morgancodes
  • 25,055
  • 38
  • 135
  • 187
  • possible duplicate of [How to create private variable accessible to Prototype function?](http://stackoverflow.com/questions/6307684/how-to-create-private-variable-accessible-to-prototype-function) – educampver Oct 10 '13 at 04:06
  • 14
    @ecampver, Except this one was asked 2 years *earlier*.... – Pacerier Jun 04 '14 at 16:36

25 Answers25

208

No, there's no way to do it. That would essentially be scoping in reverse.

Methods defined inside the constructor have access to private variables because all functions have access to the scope in which they were defined.

Methods defined on a prototype are not defined within the scope of the constructor, and will not have access to the constructor's local variables.

You can still have private variables, but if you want methods defined on the prototype to have access to them, you should define getters and setters on the this object, which the prototype methods (along with everything else) will have access to. For example:

function Person(name, secret) {
    // public
    this.name = name;

    // private
    var secret = secret;

    // public methods have access to private members
    this.setSecret = function(s) {
        secret = s;
    }

    this.getSecret = function() {
        return secret;
    }
}

// Must use getters/setters 
Person.prototype.spillSecret = function() { alert(this.getSecret()); };
Niyaz
  • 53,943
  • 55
  • 151
  • 182
Kenan Banks
  • 207,056
  • 34
  • 155
  • 173
  • 18
    "scoping in reverse" is a C++ feature with the "friend" keyword. Esentially any function should define it's prototype as it's friend. Sadly this concept is C++ and not JS :( – TWiStErRob Sep 21 '13 at 18:22
  • Also it's important to be aware that if "secret" is an object (array for example) getter will return a reference instead of value of the variable. That means person.getSecret().push(1) will push to local variable. – sznowicki Dec 14 '15 at 10:16
  • 1
    I would like to add this post to the top of my favorites list and keep it there. – Daniel Viglione Apr 16 '16 at 21:11
  • 2
    I don't see the point of this- you're only adding a layer of abstraction that doesn't do anything. You may as well just make `secret` a property of `this`. JavaScript simply doesn't support private variables with prototypes as prototypes are bound to the call-site context, not the 'creation-site' context. – nicodemus13 Jan 07 '17 at 13:03
  • 1
    Why not just do `person.getSecret()` then? – Fahmi Feb 28 '17 at 10:53
  • 1
    Why does this have so many upvotes? This doesn't make the variable private. As mentioned above using person.getSecret() will let you access that private variable from anywhere. – alexr101 Jul 18 '18 at 19:17
66

Update: With ES6, there is a better way:

Long story short, you can use the new Symbol to create private fields.
Here's a great description: https://curiosity-driven.org/private-properties-in-javascript

Example:

var Person = (function() {
    // Only Person can access nameSymbol
    var nameSymbol = Symbol('name');

    function Person(name) {
        this[nameSymbol] = name;
    }

    Person.prototype.getName = function() {
        return this[nameSymbol];
    };

    return Person;
}());

For all modern browsers with ES5:

You can use just Closures

The simplest way to construct objects is to avoid prototypal inheritance altogether. Just define the private variables and public functions within the closure, and all public methods will have private access to the variables.

Or you can use just Prototypes

In JavaScript, prototypal inheritance is primarily an optimization. It allows multiple instances to share prototype methods, rather than each instance having its own methods.
The drawback is that this is the only thing that's different each time a prototypal function is called.
Therefore, any private fields must be accessible through this, which means they're going to be public. So we just stick to naming conventions for _private fields.

Don't bother mixing Closures with Prototypes

I think you shouldn't mix closure variables with prototype methods. You should use one or the other.

When you use a closure to access a private variable, prototype methods cannot access the variable. So, you have to expose the closure onto this, which means that you're exposing it publicly one way or another. There's very little to gain with this approach.

Which do I choose?

For really simple objects, just use a plain object with closures.

If you need prototypal inheritance -- for inheritance, performance, etc. -- then stick with the "_private" naming convention, and don't bother with closures.

I don't understand why JS developers try SO hard to make fields truly private.

Scott Rippey
  • 15,614
  • 5
  • 70
  • 85
  • 5
    Sadly, the `_private` naming convention is still the best solution if you want to take advantage of prototypal inheritance. – crush Mar 03 '15 at 15:14
  • 1
    ES6 will have a new concept, the `Symbol`, which is an excellent way to create private fields. Here's a great explanation: https://curiosity-driven.org/private-properties-in-javascript – Scott Rippey Mar 03 '15 at 22:11
  • Wouldn't you have to expose the `Symbol` reference in order to access the `Symbol` in a prototype function? WeakMaps seem more like private access in that example than the `Symbol`. – crush Mar 03 '15 at 22:18
  • 1
    No, you can keep the `Symbol` in a closure that encompasses your whole class. That way, all prototype methods can use the Symbol, but it's never exposed outside the class. – Scott Rippey Mar 03 '15 at 22:21
  • The `WeakMap` solution is similar, because the WeakMap is kept in a closure too, accessible to all prototype methods. But the WeakMap's biggest drawback is the lack of garbage collection ... you've got to remove the references manually, which is a huge drawback. – Scott Rippey Mar 03 '15 at 22:23
  • 2
    The article you linked says "*Symbols are similar to private names but — unlike private names — they **do not provide true privacy**.*". Effectively, if you have the instance, you can get its symbols with `Object.getOwnPropertySymbols`. So this is only privacy by obscurity. – Oriol May 25 '15 at 01:26
  • 2
    @Oriol Yeah, the privacy is via heavy obscurity. It is still possible to iterate through the symbols, and you infer the symbol's purpose via `toString`. This is no different than Java or C# ... private members are still accessible via reflection, but are usually strongly obscured. Which all goes to strengthen my final point, "I don't understand why JS developers try SO hard to make fields truly private." – Scott Rippey May 26 '15 at 18:42
  • *"you've got to remove the references manually, which is a huge drawback"* No, that's exactly the problem `WeakMap`s solve. – Felix Kling May 10 '16 at 19:09
  • @FelixKling I was referencing a manually-implemented ES5 `WeakMap` as discussed in another answer. You're talking about ES6's native `WeakMap`, which does have garbage collection; but if you've got ES6, then `Symbol` is the best solution. – Scott Rippey May 11 '16 at 15:50
  • I think you have typo in your last line. Should be: `})();` – Yuval A. Sep 21 '16 at 09:57
  • +1 Thanks Scott for the ES5 commentary. While the accepted answer provides solution to original problem, your answer nicely outlines why we shouldn't really bother with mixing these two approaches. – J. Wrong Dec 30 '17 at 18:41
  • _I don't understand why JS developers try SO hard to make fields truly private._ -- They are Java developers trying to learn JavaScript. – Madeyedexter Mar 04 '18 at 09:40
31

When I read this, it sounded like a tough challenge so I decided to figure out a way. What I came up with was CRAAAAZY but it totally works.

First, I tried defining the class in an immediate function so you'd have access to some of the private properties of that function. This works and allows you to get some private data, however, if you try to set the private data you'll soon find that all the objects will share the same value.

var SharedPrivateClass = (function() { // use immediate function
    // our private data
    var private = "Default";

    // create the constructor
    function SharedPrivateClass() {}

    // add to the prototype
    SharedPrivateClass.prototype.getPrivate = function() {
        // It has access to private vars from the immediate function!
        return private;
    };

    SharedPrivateClass.prototype.setPrivate = function(value) {
        private = value;
    };

    return SharedPrivateClass;
})();

var a = new SharedPrivateClass();
console.log("a:", a.getPrivate()); // "a: Default"

var b = new SharedPrivateClass();
console.log("b:", b.getPrivate()); // "b: Default"

a.setPrivate("foo"); // a Sets private to "foo"
console.log("a:", a.getPrivate()); // "a: foo"
console.log("b:", b.getPrivate()); // oh no, b.getPrivate() is "foo"!

console.log(a.hasOwnProperty("getPrivate")); // false. belongs to the prototype
console.log(a.private); // undefined

// getPrivate() is only created once and instanceof still works
console.log(a.getPrivate === b.getPrivate);
console.log(a instanceof SharedPrivateClass);
console.log(b instanceof SharedPrivateClass);

There are plenty of cases where this would be adequate like if you wanted to have constant values like event names that get shared between instances. But essentially, they act like private static variables.

If you absolutely need access to variables in a private namespace from within your methods defined on the prototype, you can try this pattern.

var PrivateNamespaceClass = (function() { // immediate function
    var instance = 0, // counts the number of instances
        defaultName = "Default Name",  
        p = []; // an array of private objects

    // create the constructor
    function PrivateNamespaceClass() {
        // Increment the instance count and save it to the instance. 
        // This will become your key to your private space.
        this.i = instance++; 
        
        // Create a new object in the private space.
        p[this.i] = {};
        // Define properties or methods in the private space.
        p[this.i].name = defaultName;
        
        console.log("New instance " + this.i);        
    }

    PrivateNamespaceClass.prototype.getPrivateName = function() {
        // It has access to the private space and it's children!
        return p[this.i].name;
    };
    PrivateNamespaceClass.prototype.setPrivateName = function(value) {
        // Because you use the instance number assigned to the object (this.i)
        // as a key, the values set will not change in other instances.
        p[this.i].name = value;
        return "Set " + p[this.i].name;
    };

    return PrivateNamespaceClass;
})();

var a = new PrivateNamespaceClass();
console.log(a.getPrivateName()); // Default Name

var b = new PrivateNamespaceClass();
console.log(b.getPrivateName()); // Default Name

console.log(a.setPrivateName("A"));
console.log(b.setPrivateName("B"));
console.log(a.getPrivateName()); // A
console.log(b.getPrivateName()); // B

// private objects are not accessible outside the PrivateNamespaceClass function
console.log(a.p);

// the prototype functions are not re-created for each instance
// and instanceof still works
console.log(a.getPrivateName === b.getPrivateName);
console.log(a instanceof PrivateNamespaceClass);
console.log(b instanceof PrivateNamespaceClass);

I'd love some feedback from anyone who sees an error with this way of doing it.

Yay295
  • 1,628
  • 3
  • 17
  • 29
Mims H. Wright
  • 3,049
  • 1
  • 25
  • 30
  • 4
    I guess one potential concern is that any instance could access any other instances private vars by using a different instance id. Not necessarily a bad thing... – Mims H. Wright Dec 13 '12 at 09:46
  • The important thing to note is that it works as expected, making it at least viable as a way of achieving that effect. Whether it's the best way or a way that adheres to standards and best practices isn't really something I can safely say. To me it seems a good way to do it that doesn't seem to have any huge, obvious problems. Just my 2 cents. – Hendeca Dec 13 '12 at 21:05
  • 15
    You redefine prototype functions upon every constructor call – Lu4 Feb 06 '13 at 15:58
  • 10
    @Lu4 I'm not sure that's true. The constructor is returned from within a closure; the only time the prototype functions are defined is the first time, in that immediately invoked function expression. Privacy issues that were mentioned above aside, this looks good to me (at first glance). – guypursey Feb 24 '13 at 13:19
  • 1
    @MimsH.Wright other languages allow for access to other objects privates **of the same class**, but only when you have reference to them. To allow for this you could hide the privates behind a function that takes the objects pointer as the key (as apposed to an ID). That way you only have access to private data of objects you know about, which is more inline with scoping in other languages. However, this implementation sheds light on a deeper problem with this. The private objects will never be Garbage Collected until the Constructor function is. – Thomas Nadin Mar 26 '13 at 16:04
  • Good point about the garbage collection. I suppose you could do `delete p[this.i]` but it wouldn't be automatic. – Mims H. Wright Mar 28 '13 at 00:27
  • Incidentally, I originally thought about making the variable `this` have a pointer to itself called `r` and `i` would be `ivate` so you could write `p[r.ivate]` but decided it was too silly. Or maybe it didn't work outside the constructor. Anyway, if anyone can figure out a nicer shorthand than `p[this.i]`, that would be cool. – Mims H. Wright Mar 28 '13 at 00:33
  • Never mind the nicer shorthand, you have `privateNamespace` as a global variable! – MikeM Apr 05 '13 at 15:30
  • @MikeM Oh my gosh, you're right! I fixed it. How does that work? why is it public? – Mims H. Wright Apr 05 '13 at 20:34
  • You hadn't properly declared it in the local scope. All the private data was exposed. See [Difference between using var and not using var in JavaScript](http://stackoverflow.com/questions/1470488/difference-between-using-var-and-not-using-var-in-javascript). – MikeM Apr 05 '13 at 21:23
  • Don't you have a memory leak? – Paul Draper Jun 09 '13 at 02:20
  • It's not that crazy: http://www.codeproject.com/Articles/133118/Safe-Factory-Pattern-Private-instance-state-in-Jav – TWiStErRob Sep 21 '13 at 20:58
  • 3
    I want to mention that `i` has been added to all instances. So it's not fully "transparent", and `i` could still be tampered with. – Scott Rippey Feb 03 '14 at 07:19
  • This is the same concept as **Inside-out Objects** in the book "Perl Best Practices" by Damian Conway. – Jess Feb 17 '14 at 13:56
  • Caution: `delete` does not free memory. It does not trigger any garbage collection unless the deleted prop is the final reference. – Onur Yıldırım Dec 08 '14 at 02:41
  • 1
    Has anyone done any in depth testing of @Lu4's comment? I suspect he's right. On each new of the `PrivateNamespaceClass`, you are creating a new closure instance, which is creating a new instance of the inner function and prototype. – crush Mar 03 '15 at 15:21
  • Instead of making `this.i` a normal property, you could use `Object.defineProperty` to make it a non-writable property. Then it would be even more secure. – Gabriel L. Jul 26 '15 at 04:24
  • Seems a very nice solution to me, I was checking execution time and memory cost, all fine. Someone mentioned about memory leak, how can I check against this solution? – Ricardo Silva Jan 24 '16 at 01:55
  • This doesn't seem to have any advantage over declaring all the methods in the constructor (not using `prototype` at all), since you're still creating new Function objects for every instance of the class. I think it also has the disadvantage of breaking `instanceof`. – peterflynn Dec 05 '17 at 23:05
  • Your second exemple implements the static private variable too. Every time you will call the constructor the private variables will be shared between instances. I tried your example with a mine more simple example and doesn't work and also the early logical analysis suggests me that your example is wrong – Nick Apr 17 '20 at 23:35
19

see Doug Crockford's page on this. You have to do it indirectly with something that can access the scope of the private variable.

another example:

Incrementer = function(init) {
  var counter = init || 0;  // "counter" is a private variable
  this._increment = function() { return counter++; }
  this._set = function(x) { counter = x; }
}
Incrementer.prototype.increment = function() { return this._increment(); }
Incrementer.prototype.set = function(x) { return this._set(x); }

use case:

js>i = new Incrementer(100);
[object Object]
js>i.increment()
100
js>i.increment()
101
js>i.increment()
102
js>i.increment()
103
js>i.set(-44)
js>i.increment()
-44
js>i.increment()
-43
js>i.increment()
-42
Jason S
  • 184,598
  • 164
  • 608
  • 970
  • 47
    This example seems to be terrible practice. The point of using prototype methods is so that you don't have to create a new one for every instance. You're doing that anyway. For every method you're creating another one. – Kir Apr 05 '12 at 12:46
  • 2
    @ArmedMonkey The concept looks sound, but agreed this is a bad example because the prototype functions shown are trivial. If the prototype functions were much longer functions requiring simple get/set access to the 'private' variables it would make sense. – pancake Apr 19 '13 at 18:59
  • 9
    Why even bother exposing `_set` via `set`? Why not just name it `set` to begin with? – Scott Rippey Feb 16 '14 at 09:01
15

I suggest it would probably be a good idea to describe "having a prototype assignment in a constructor" as a Javascript anti-pattern. Think about it. It is way too risky.

What you're actually doing there on creation of the second object (i.e. b) is redefining that prototype function for all objects that use that prototype. This will effectively reset the value for object a in your example. It will work if you want a shared variable and if you happen to create all of the object instances up front, but it feels way too risky.

I found a bug in some Javascript I was working on recently that was due to this exact anti-pattern. It was trying to set a drag and drop handler on the particular object being created but was instead doing it for all instances. Not good.

Doug Crockford's solution is the best.

Lance Ewing
  • 151
  • 1
  • 2
10

@Kai

That won't work. If you do

var t2 = new TestClass();

then t2.prototypeHello will be accessing t's private section.

@AnglesCrimes

The sample code works fine, but it actually creates a "static" private member shared by all instances. It may not be the solution morgancodes looked for.

So far I haven't found an easy and clean way to do this without introducing a private hash and extra cleanup functions. A private member function can be simulated to certain extent:

(function() {
    function Foo() { ... }
    Foo.prototype.bar = function() {
       privateFoo.call(this, blah);
    };
    function privateFoo(blah) { 
        // scoped to the instance by passing this to call 
    }

    window.Foo = Foo;
}());
Maksim Vi.
  • 9,107
  • 12
  • 59
  • 85
Tim
  • 141
  • 1
  • 3
  • Understood your points clearly, but can u please explain what is your code snippet trying to do? – Vishwanath Oct 14 '12 at 10:32
  • `privateFoo` is completely private and thus invisible when getting a `new Foo()`. Only `bar()` is a public method here, which has access to `privateFoo`. You could use the same mechanism for simple variables and objects, however you need to always keep in mind that those `privates` are actually static and will be shared by all objects you create. – Philzen May 09 '13 at 20:37
7

Yes, it's possible. PPF design pattern just solves this.

PPF stands for Private Prototype Functions. Basic PPF solves these issues:

  1. Prototype functions get access to private instance data.
  2. Prototype functions can be made private.

For the first, just:

  1. Put all private instance variables you want to be accessible from prototype functions inside a separate data container, and
  2. Pass a reference to the data container to all prototype functions as a parameter.

It's that simple. For example:

// Helper class to store private data.
function Data() {};

// Object constructor
function Point(x, y)
{
  // container for private vars: all private vars go here
  // we want x, y be changeable via methods only
  var data = new Data;
  data.x = x;
  data.y = y;

  ...
}

// Prototype functions now have access to private instance data
Point.prototype.getX = function(data)
{
  return data.x;
}

Point.prototype.getY = function(data)
{
  return data.y;
}

...

Read the full story here:

PPF Design Pattern

Edward
  • 91
  • 1
  • 5
  • 4
    Link-only answer are generally frowned upon on SO. Please show an example. – Corey Adler Nov 19 '13 at 21:07
  • The article has examples inside, so please see there – Edward Nov 19 '13 at 21:20
  • 5
    What happens, though, if at some point later on that site goes down? How is someone supposed to see an example then? The policy is in place so that anything of value in a link can be kept here, and not have to rely on a website that this is not under our control. – Corey Adler Nov 19 '13 at 22:48
  • 3
    @Edward, your link is an interesting read! However, it seems to me that the major reason to access private data using prototypical functions, is to prevent that every object wastes memory with identical public functions. The method you describe does not solve this problem, since for public usage, a prototypical function needs to be wrapped in a regular public function. I guess the pattern could be useful for saving memory if you have a lot of ppf's which are combined in a single public function. Do you use them for anything else? – Dining Philosopher Dec 18 '13 at 23:22
  • @DiningPhilosofer, thank you for appreciating my article. Yes, you are right, we still use instance functions. But the idea is to have them as lightweight as possible by just re-calling their PPF counterparts which do all the heavy work. Eventually all instances call the same PPFs (via wrappers of course), so a certain memory saving may be expected. The question is how much. I expect substantial saving. – Edward Jan 02 '14 at 20:10
5

You can actually achieve this by using Accessor Verification:

(function(key, global) {
  // Creates a private data accessor function.
  function _(pData) {
    return function(aKey) {
      return aKey === key && pData;
    };
  }

  // Private data accessor verifier.  Verifies by making sure that the string
  // version of the function looks normal and that the toString function hasn't
  // been modified.  NOTE:  Verification can be duped if the rogue code replaces
  // Function.prototype.toString before this closure executes.
  function $(me) {
    if(me._ + '' == _asString && me._.toString === _toString) {
      return me._(key);
    }
  }
  var _asString = _({}) + '', _toString = _.toString;

  // Creates a Person class.
  var PersonPrototype = (global.Person = function(firstName, lastName) {
    this._ = _({
      firstName : firstName,
      lastName : lastName
    });
  }).prototype;
  PersonPrototype.getName = function() {
    var pData = $(this);
    return pData.firstName + ' ' + pData.lastName;
  };
  PersonPrototype.setFirstName = function(firstName) {
    var pData = $(this);
    pData.firstName = firstName;
    return this;
  };
  PersonPrototype.setLastName = function(lastName) {
    var pData = $(this);
    pData.lastName = lastName;
    return this;
  };
})({}, this);

var chris = new Person('Chris', 'West');
alert(chris.setFirstName('Christopher').setLastName('Webber').getName());

This example comes from my post about Prototypal Functions & Private Data and is explained in more detail there.

Chris West
  • 885
  • 8
  • 17
Chris West
  • 59
  • 1
  • 1
  • 1
    This answer is too "clever" to be useful, but I like the answer of using an IFFE-bound variable as a secret handshake. This implementation uses too many closures to be useful; the point of having prototype defined methods is to prevent the construction of new function objects for each method on each object. – Grae Kindel Aug 15 '13 at 11:59
  • This approach uses a secret key to identify which prototype methods are trusted and which aren't. However, it's the instance who validates the key, so the key must be sent to the instance. But then, untrusted code could call a trusted method on a fake instance, which would steal the key. And with that key, make new methods which would be considered trusted by real instances. So this is only privacy by obscurity. – Oriol Oct 17 '15 at 19:53
5

In current JavaScript, I'm fairly certain that there is one and only one way to have private state, accessible from prototype functions, without adding anything public to this. The answer is to use the "weak map" pattern.

To sum it up: The Person class has a single weak map, where the keys are the instances of Person, and the values are plain objects that are used for private storage.

Here is a fully functional example: (play at http://jsfiddle.net/ScottRippey/BLNVr/)

var Person = (function() {
    var _ = weakMap();
    // Now, _(this) returns an object, used for private storage.
    var Person = function(first, last) {
        // Assign private storage:
        _(this).firstName = first;
        _(this).lastName = last;
    }
    Person.prototype = {
        fullName: function() {
            // Retrieve private storage:
            return _(this).firstName + _(this).lastName;
        },
        firstName: function() {
            return _(this).firstName;
        },
        destroy: function() {
            // Free up the private storage:
            _(this, true);
        }
    };
    return Person;
})();

function weakMap() {
    var instances=[], values=[];
    return function(instance, destroy) {
        var index = instances.indexOf(instance);
        if (destroy) {
            // Delete the private state:
            instances.splice(index, 1);
            return values.splice(index, 1)[0];
        } else if (index === -1) {
            // Create the private state:
            instances.push(instance);
            values.push({});
            return values[values.length - 1];
        } else {
            // Return the private state:
            return values[index];
        }
    };
}

Like I said, this is really the only way to achieve all 3 parts.

There are two caveats, however. First, this costs performance -- every time you access the private data, it's an O(n) operation, where n is the number of instances. So you won't want to do this if you have a large number of instances. Second, when you're done with an instance, you must call destroy; otherwise, the instance and the data will not be garbage collected, and you'll end up with a memory leak.

And that's why my original answer, "You shouldn't", is something I'd like to stick to.

Scott Rippey
  • 15,614
  • 5
  • 70
  • 85
  • If you don't explicitly destroy an instance of Person before it goes out of scope doesn't the weakmap keep a reference to it so you'll have a memory leak? I came up with a pattern for **protected** as other instances of Person can access the variable and those inheriting from Person can. Just fiddled it out so not sure if there are any dis advantages other than extra processing (doesn't look as much as accessing the privates) http://stackoverflow.com/a/21800194/1641941 Returning a private/protected object is a pain since calling code can then mutate your private/protected. – HMR Feb 16 '14 at 14:22
  • 2
    @HMR Yeah, you have to explicitly destroy the private data. I'm going to add this caveat to my answer. – Scott Rippey Feb 16 '14 at 23:27
3

There's a simpler way by leveraging the use of bind and call methods.

By setting private variables to an object, you can leverage that object's scope.

Example

function TestClass (value) {
    // The private value(s)
    var _private = {
        value: value
    };

    // `bind` creates a copy of `getValue` when the object is instantiated
    this.getValue = TestClass.prototype.getValue.bind(_private);

    // Use `call` in another function if the prototype method will possibly change
    this.getValueDynamic = function() {
        return TestClass.prototype.getValue.call(_private);
    };
};

TestClass.prototype.getValue = function() {
    return this.value;
};

This method isn't without drawbacks. Since the scope context is effectively being overridden, you don't have access outside of the _private object. However, it isn't impossible though to still give access to the instance object's scope. You can pass in the object's context (this) as the second argument to bind or call to still have access to it's public values in the prototype function.

Accessing public values

function TestClass (value) {
    var _private = {
        value: value
    };

    this.message = "Hello, ";

    this.getMessage = TestClass.prototype.getMessage.bind(_private, this);

}

TestClass.prototype.getMessage = function(_public) {

    // Can still access passed in arguments
    // e.g. – test.getValues('foo'), 'foo' is the 2nd argument to the method
    console.log([].slice.call(arguments, 1));
    return _public.message + this.value;
};

var test = new TestClass("World");
test.getMessage(1, 2, 3); // [1, 2, 3]         (console.log)
                          // => "Hello, World" (return value)

test.message = "Greetings, ";
test.getMessage(); // []                    (console.log)
                   // => "Greetings, World" (return value)
thgaskell
  • 12,772
  • 5
  • 32
  • 38
  • 2
    Why would someone create a copy of the prototype method as opposed to just creating an instanced method in the first place? – crush Mar 03 '15 at 15:10
3

Try it!

    function Potatoe(size) {
    var _image = new Image();
    _image.src = 'potatoe_'+size+'.png';
    function getImage() {
        if (getImage.caller == null || getImage.caller.owner != Potatoe.prototype)
            throw new Error('This is a private property.');
        return _image;
    }
    Object.defineProperty(this,'image',{
        configurable: false,
        enumerable: false,
        get : getImage          
    });
    Object.defineProperty(this,'size',{
        writable: false,
        configurable: false,
        enumerable: true,
        value : size            
    });
}
Potatoe.prototype.draw = function(ctx,x,y) {
    //ctx.drawImage(this.image,x,y);
    console.log(this.image);
}
Potatoe.prototype.draw.owner = Potatoe.prototype;

var pot = new Potatoe(32);
console.log('Potatoe size: '+pot.size);
try {
    console.log('Potatoe image: '+pot.image);
} catch(e) {
    console.log('Oops: '+e);
}
pot.draw();
AlanNLohse
  • 43
  • 1
  • 6
  • 1
    This relies on `caller`, which is an implementation-dependent extension not allowed in strict-mode. – Oriol Oct 17 '15 at 16:08
1

Here's what I came up with.

(function () {
    var staticVar = 0;
    var yrObj = function () {
        var private = {"a":1,"b":2};
        var MyObj = function () {
            private.a += staticVar;
            staticVar++;
        };
        MyObj.prototype = {
            "test" : function () {
                console.log(private.a);
            }
        };

        return new MyObj;
    };
    window.YrObj = yrObj;
}());

var obj1 = new YrObj;
var obj2 = new YrObj;
obj1.test(); // 1
obj2.test(); // 2

the main problem with this implementation is that it redefines the prototypes on every instanciation.

Xeltor
  • 4,626
  • 3
  • 24
  • 26
  • Interesting, I really like the attempt and was thinking of same thing, but you're right that redefining the prototype function on every instantiation is a pretty big limitation. This is not just because it's wasted CPU cycles, but because if you ever change the prototoype later on, it would get "reset" back to its original state as defined in the constructor upon the next instantiation :/ – Niko Bellic Sep 05 '15 at 20:31
  • 1
    This not only redefined prototypes, it defines a new constructor for each instance. So the "instances" are no longer instances of the same class. – Oriol Oct 17 '15 at 16:11
1

There is a very simple way to do this

function SharedPrivate(){
  var private = "secret";
  this.constructor.prototype.getP = function(){return private}
  this.constructor.prototype.setP = function(v){ private = v;}
}

var o1 = new SharedPrivate();
var o2 = new SharedPrivate();

console.log(o1.getP()); // secret
console.log(o2.getP()); // secret
o1.setP("Pentax Full Frame K1 is on sale..!");
console.log(o1.getP()); // Pentax Full Frame K1 is on sale..!
console.log(o2.getP()); // Pentax Full Frame K1 is on sale..!
o2.setP("And it's only for $1,795._");
console.log(o1.getP()); // And it's only for $1,795._

JavaScript prototypes are golden.

Redu
  • 25,060
  • 6
  • 56
  • 76
  • 2
    I believe it's better not to use prototype in constructor function as it will create a new function every time a new instance is created. – whamsicore Jul 29 '16 at 06:43
  • @whamsicore Yes true but in this case it's essential since for every single object instantiated we have to arrange a shared closure. That's the reason why the function definitions reside inside the constructor and we have to refer to the `SharedPrivate.prototype` as `this.constructor.prototype` It's no big deal to redefine getP and setP multiple times... – Redu Jul 29 '16 at 07:16
1

I'm late to the party, but I think I can contribute. Here, check this out:

// 1. Create closure
var SomeClass = function() {
  // 2. Create `key` inside a closure
  var key = {};
  // Function to create private storage
  var private = function() {
    var obj = {};
    // return Function to access private storage using `key`
    return function(testkey) {
      if(key === testkey) return obj;
      // If `key` is wrong, then storage cannot be accessed
      console.error('Cannot access private properties');
      return undefined;
    };
  };
  var SomeClass = function() {
    // 3. Create private storage
    this._ = private();
    // 4. Access private storage using the `key`
    this._(key).priv_prop = 200;
  };
  SomeClass.prototype.test = function() {
    console.log(this._(key).priv_prop); // Using property from prototype
  };
  return SomeClass;
}();

// Can access private property from within prototype
var instance = new SomeClass();
instance.test(); // `200` logged

// Cannot access private property from outside of the closure
var wrong_key = {};
instance._(wrong_key); // undefined; error logged

I call this method accessor pattern. The essential idea is that we have a closure, a key inside the closure, and we create a private object (in the constructor) that can only be accessed if you have the key.

If you are interested, you can read more about this in my article. Using this method, you can create per object properties that cannot be accessed outside of the closure. Therefore, you can use them in constructor or prototype, but not anywhere else. I haven't seen this method used anywhere, but I think it's really powerful.

guitarino
  • 348
  • 1
  • 7
0

Can't you put the variables in a higher scope?

(function () {
    var privateVariable = true;

    var MyClass = function () {
        if (privateVariable) console.log('readable from private scope!');
    };

    MyClass.prototype.publicMethod = function () {
        if (privateVariable) console.log('readable from public scope!');
    };
}))();
Ev Haus
  • 1,578
  • 1
  • 11
  • 23
0

You can also try to add method not directly on prototype, but on constructor function like this:

var MyArray = function() {
    var array = [];

    this.add = MyArray.add.bind(null, array);
    this.getAll = MyArray.getAll.bind(null, array);
}

MyArray.add = function(array, item) {
    array.push(item);
}
MyArray.getAll = function(array) {
    return array;
}

var myArray1 = new MyArray();
myArray1.add("some item 1");
console.log(myArray1.getAll()); // ['some item 1']
var myArray2 = new MyArray();
myArray2.add("some item 2");
console.log(myArray2.getAll()); // ['some item 2']
console.log(myArray1.getAll()); // ['some item 2'] - FINE!
Maciej Dzikowicki
  • 859
  • 1
  • 10
  • 10
0

Here's something I've come up with while trying to find most simple solution for this problem, perhaps it could be useful to someone. I'm new to javascript, so there might well be some issues with the code.

// pseudo-class definition scope
(function () {

    // this is used to identify 'friend' functions defined within this scope,
    // while not being able to forge valid parameter for GetContext() 
    // to gain 'private' access from outside
    var _scope = new (function () { })();
    // -----------------------------------------------------------------

    // pseudo-class definition
    this.Something = function (x) {

        // 'private' members are wrapped into context object,
        // it can be also created with a function
        var _ctx = Object.seal({

            // actual private members
            Name: null,
            Number: null,

            Somefunc: function () {
                console.log('Something(' + this.Name + ').Somefunc(): number = ' + this.Number);
            }
        });
        // -----------------------------------------------------------------

        // function below needs to be defined in every class
        // to allow limited access from prototype
        this.GetContext = function (scope) {

            if (scope !== _scope) throw 'access';
            return _ctx;
        }
        // -----------------------------------------------------------------

        {
            // initialization code, if any
            _ctx.Name = (x !== 'undefined') ? x : 'default';
            _ctx.Number = 0;

            Object.freeze(this);
        }
    }
    // -----------------------------------------------------------------

    // prototype is defined only once
    this.Something.prototype = Object.freeze({

        // public accessors for 'private' field
        get Number() { return this.GetContext(_scope).Number; },
        set Number(v) { this.GetContext(_scope).Number = v; },

        // public function making use of some private fields
        Test: function () {

            var _ctx = this.GetContext(_scope);
            // access 'private' field
            console.log('Something(' + _ctx.Name + ').Test(): ' + _ctx.Number);
            // call 'private' func
            _ctx.Somefunc();
        }
    });
    // -----------------------------------------------------------------

    // wrap is used to hide _scope value and group definitions
}).call(this);

function _A(cond) { if (cond !== true) throw new Error('assert failed'); }
// -----------------------------------------------------------------

function test_smth() {

    console.clear();

    var smth1 = new Something('first'),
      smth2 = new Something('second');

    //_A(false);
    _A(smth1.Test === smth2.Test);

    smth1.Number = 3;
    smth2.Number = 5;
    console.log('smth1.Number: ' + smth1.Number + ', smth2.Number: ' + smth2.Number);

    smth1.Number = 2;
    smth2.Number = 6;

    smth1.Test();
    smth2.Test();

    try {
        var ctx = smth1.GetContext();
    } catch (err) {
        console.log('error: ' + err);
    }
}

test_smth();
V.Mihaly4
  • 1
  • 1
0

I faced the exact same question today and after elaborating on Scott Rippey first-class response, I came up with a very simple solution (IMHO) that is both compatible with ES5 and efficient, it also is name clash safe (using _private seems unsafe).

/*jslint white: true, plusplus: true */

 /*global console */

var a, TestClass = (function(){
    "use strict";
    function PrefixedCounter (prefix) {
        var counter = 0;
        this.count = function () {
            return prefix + (++counter);
        };
    }
    var TestClass = (function(){
        var cls, pc = new PrefixedCounter("_TestClass_priv_")
        , privateField = pc.count()
        ;
        cls = function(){
            this[privateField] = "hello";
            this.nonProtoHello = function(){
                console.log(this[privateField]);
            };
        };
        cls.prototype.prototypeHello = function(){
            console.log(this[privateField]);
        };
        return cls;
    }());
    return TestClass;
}());

a = new TestClass();
a.nonProtoHello();
a.prototypeHello();

Tested with ringojs and nodejs. I'm eager to read your opinion.

alexgirao
  • 885
  • 9
  • 9
  • Here is a reference: check the 'A step closer' section. https://philipwalton.com/articles/implementing-private-and-protected-members-in-javascript/ – jimasun Feb 15 '17 at 18:50
0
var getParams = function(_func) {
  res = _func.toString().split('function (')[1].split(')')[0].split(',')
  return res
}

function TestClass(){

  var private = {hidden: 'secret'}
  //clever magic accessor thing goes here
  if ( !(this instanceof arguments.callee) ) {
    for (var key in arguments) {
      if (typeof arguments[key] == 'function') {
        var keys = getParams(arguments[key])
        var params = []
        for (var i = 0; i <= keys.length; i++) {
          if (private[keys[i]] != undefined) {
            params.push(private[keys[i]])
          }
        }
        arguments[key].apply(null,params)
      }
    }
  }
}


TestClass.prototype.test = function(){
  var _hidden; //variable I want to get
  TestClass(function(hidden) {_hidden = hidden}) //invoke magic to get
};

new TestClass().test()

How's this? Using an private accessor. Only allows you to get the variables though not to set them, depends on the use case.

dylan0150
  • 1
  • 2
  • This does **not** answer the question in a useful way. _why_ do you believe this is the answer? _how_ does it work? Simply telling someone to _change their code_ without any context or meaning does not help them learn what they did wrong. – GrumpyCrouton Jun 08 '17 at 16:33
  • He wanted a way to access hidden private variables of a Class via prototypes without having to create that hidden variable on every single instance of the class. The above code is an example method of doing such that. How is that not an answer to the question? – dylan0150 Jun 08 '17 at 16:37
  • I didn't say it wasn't an answer to the question. I said it wasn't a _useful_ answer, because it doesn't help anyone learn. You should explain your code, _why_ it works, _why_ it's the right way to do it. If I was the question author, I wouldn't accept your answer because it doesn't encourage learning, it doesn't teach me what I'm doing wrong or what the given code is doing or how it works. – GrumpyCrouton Jun 08 '17 at 16:54
0

I have one solution, but I am not sure it is without flaws.

For it to work, you have to use the following structure:

  1. Use 1 private object that contains all private variables.
  2. Use 1 instance function.
  3. Apply a closure to the constructor and all prototype functions.
  4. Any instance created is done outside the closure defined.

Here is the code:

var TestClass = 
(function () {
    // difficult to be guessed.
    var hash = Math.round(Math.random() * Math.pow(10, 13) + + new Date());
    var TestClass = function () {
        var privateFields = {
            field1: 1,
            field2: 2
        };
        this.getPrivateFields = function (hashed) {
            if(hashed !== hash) {
                throw "Cannot access private fields outside of object.";
                // or return null;
            }
            return privateFields;
        };
    };

    TestClass.prototype.prototypeHello = function () {
        var privateFields = this.getPrivateFields(hash);
        privateFields.field1 = Math.round(Math.random() * 100);
        privateFields.field2 = Math.round(Math.random() * 100);
    };

    TestClass.prototype.logField1 = function () {
        var privateFields = this.getPrivateFields(hash);
        console.log(privateFields.field1);
    };

    TestClass.prototype.logField2 = function () {
        var privateFields = this.getPrivateFields(hash);
        console.log(privateFields.field2);
    };

    return TestClass;
})();

How this works is that it provides an instance function "this.getPrivateFields" to access the "privateFields" private variables object, but this function will only return the "privateFields" object inside the main closure defined (also prototype functions using "this.getPrivateFields" need to be defined inside this closure).

A hash produced during runtime and difficult to be guessed is used as parameters to make sure that even if "getPrivateFields" is called outside the scope of closure will not return the "privateFields" object.

The drawback is that we can not extend TestClass with more prototype functions outside the closure.

Here is some test code:

var t1 = new TestClass();
console.log('Initial t1 field1 is: ');
t1.logField1();
console.log('Initial t1 field2 is: ');
t1.logField2();
t1.prototypeHello();
console.log('t1 field1 is now: ');
t1.logField1();
console.log('t1 field2 is now: ');
t1.logField2();
var t2 = new TestClass();
console.log('Initial t2 field1 is: ');
t2.logField1();
console.log('Initial t2 field2 is: ');
t2.logField2();
t2.prototypeHello();
console.log('t2 field1 is now: ');
t2.logField1();
console.log('t2 field2 is now: ');
t2.logField2();

console.log('t1 field1 stays: ');
t1.logField1();
console.log('t1 field2 stays: ');
t1.logField2();

t1.getPrivateFields(11233);

EDIT: Using this method, it is also possible to "define" private functions.

TestClass.prototype.privateFunction = function (hashed) {
    if(hashed !== hash) {
        throw "Cannot access private function.";
    }
};

TestClass.prototype.prototypeHello = function () {
    this.privateFunction(hash);
};
Jannes Botis
  • 11,154
  • 3
  • 21
  • 39
0

Was playing around with this today and this was the only solution I could find without using Symbols. Best thing about this is it can actually all be completely private.

The solution is based around a homegrown module loader which basically becomes the mediator for a private storage cache (using a weak map).

   const loader = (function() {
        function ModuleLoader() {}

    //Static, accessible only if truly needed through obj.constructor.modules
    //Can also be made completely private by removing the ModuleLoader prefix.
    ModuleLoader.modulesLoaded = 0;
    ModuleLoader.modules = {}

    ModuleLoader.prototype.define = function(moduleName, dModule) {
        if (moduleName in ModuleLoader.modules) throw new Error('Error, duplicate module');

        const module = ModuleLoader.modules[moduleName] = {}

        module.context = {
            __moduleName: moduleName,
            exports: {}
        }

        //Weak map with instance as the key, when the created instance is garbage collected or goes out of scope this will be cleaned up.
        module._private = {
            private_sections: new WeakMap(),
            instances: []
        };

        function private(action, instance) {
            switch (action) {
                case "create":
                    if (module._private.private_sections.has(instance)) throw new Error('Cannot create private store twice on the same instance! check calls to create.')
                    module._private.instances.push(instance);
                    module._private.private_sections.set(instance, {});
                    break;
                case "delete":
                    const index = module._private.instances.indexOf(instance);
                    if (index == -1) throw new Error('Invalid state');
                    module._private.instances.slice(index, 1);
                    return module._private.private_sections.delete(instance);
                    break;
                case "get":
                    return module._private.private_sections.get(instance);
                    break;
                default:
                    throw new Error('Invalid action');
                    break;
            }
        }

        dModule.call(module.context, private);
        ModuleLoader.modulesLoaded++;
    }

    ModuleLoader.prototype.remove = function(moduleName) {
        if (!moduleName in (ModuleLoader.modules)) return;

        /*
            Clean up as best we can.
        */
        const module = ModuleLoader.modules[moduleName];
        module.context.__moduleName = null;
        module.context.exports = null;
        module.cotext = null;
        module._private.instances.forEach(function(instance) { module._private.private_sections.delete(instance) });
        for (let i = 0; i < module._private.instances.length; i++) {
            module._private.instances[i] = undefined;
        }
        module._private.instances = undefined;
        module._private = null;
        delete ModuleLoader.modules[moduleName];
        ModuleLoader.modulesLoaded -= 1;
    }


    ModuleLoader.prototype.require = function(moduleName) {
        if (!(moduleName in ModuleLoader.modules)) throw new Error('Module does not exist');

        return ModuleLoader.modules[moduleName].context.exports;
    }



     return new ModuleLoader();
    })();

    loader.define('MyModule', function(private_store) {
        function MyClass() {
            //Creates the private storage facility. Called once in constructor.
            private_store("create", this);


            //Retrieve the private storage object from the storage facility.
            private_store("get", this).no = 1;
        }

        MyClass.prototype.incrementPrivateVar = function() {
            private_store("get", this).no += 1;
        }

        MyClass.prototype.getPrivateVar = function() {
            return private_store("get", this).no;
        }

        this.exports = MyClass;
    })

    //Get whatever is exported from MyModule
    const MyClass = loader.require('MyModule');

    //Create a new instance of `MyClass`
    const myClass = new MyClass();

    //Create another instance of `MyClass`
    const myClass2 = new MyClass();

    //print out current private vars
    console.log('pVar = ' + myClass.getPrivateVar())
    console.log('pVar2 = ' + myClass2.getPrivateVar())

    //Increment it
    myClass.incrementPrivateVar()

    //Print out to see if one affected the other or shared
    console.log('pVar after increment = ' + myClass.getPrivateVar())
    console.log('pVar after increment on other class = ' + myClass2.getPrivateVar())

    //Clean up.
    loader.remove('MyModule')
Eladian
  • 958
  • 10
  • 29
0

I know it has been more than 1 decade since this was was asked, but I just put my thinking on this for the n-th time in my programmer life, and found a possible solution that I don't know if I entirely like yet. I have not seen this methodology documented before, so I will name it the "private/public dollar pattern" or _$ / $ pattern.

var ownFunctionResult = this.$("functionName"[, arg1[, arg2 ...]]);
var ownFieldValue = this._$("fieldName"[, newValue]);

var objectFunctionResult = objectX.$("functionName"[, arg1[, arg2 ...]]);

//Throws an exception. objectX._$ is not defined
var objectFieldValue = objectX._$("fieldName"[, newValue]);

The concept uses a ClassDefinition function that returns a Constructor function that returns an Interface object. The interface's only method is $ which receives a name argument to invoke the corresponding function in the constructor object, any additional arguments passed after name are passed in the invocation.

The globally-defined helper function ClassValues stores all fields in an object as needed. It defines the _$ function to access them by name. This follows a short get/set pattern so if value is passed, it will be used as the new variable value.

var ClassValues = function (values) {
  return {
    _$: function _$(name, value) {
      if (arguments.length > 1) {
        values[name] = value;
      }

      return values[name];
    }
  };
};

The globally defined function Interface takes an object and a Values object to return an _interface with one single function $ that examines obj to find a function named after the parameter name and invokes it with values as the scoped object. The additional arguments passed to $ will be passed on the function invocation.

var Interface = function (obj, values, className) {
  var _interface = {
    $: function $(name) {
      if (typeof(obj[name]) === "function") {
        return obj[name].apply(values, Array.prototype.splice.call(arguments, 1));
      }

      throw className + "." + name + " is not a function.";
    }
  };

  //Give values access to the interface.
  values.$ = _interface.$;

  return _interface;
};

In the sample below, ClassX is assigned to the result of ClassDefinition, which is the Constructor function. Constructor may receive any number of arguments. Interface is what external code gets after calling the constructor.

var ClassX = (function ClassDefinition () {
  var Constructor = function Constructor (valA) {
    return Interface(this, ClassValues({ valA: valA }), "ClassX");
  };

  Constructor.prototype.getValA = function getValA() {
    //private value access pattern to get current value.
    return this._$("valA");
  };

  Constructor.prototype.setValA = function setValA(valA) {
    //private value access pattern to set new value.
    this._$("valA", valA);
  };

  Constructor.prototype.isValAValid = function isValAValid(validMessage, invalidMessage) {
    //interface access pattern to call object function.
    var valA = this.$("getValA");

    //timesAccessed was not defined in constructor but can be added later...
    var timesAccessed = this._$("timesAccessed");

    if (timesAccessed) {
      timesAccessed = timesAccessed + 1;
    } else {
      timesAccessed = 1;
    }

    this._$("timesAccessed", timesAccessed);

    if (valA) {
      return "valA is " + validMessage + ".";
    }

    return "valA is " + invalidMessage + ".";
  };

  return Constructor;
}());

There is no point in having non-prototyped functions in Constructor, although you could define them in the constructor function body. All functions are called with the public dollar pattern this.$("functionName"[, param1[, param2 ...]]). The private values are accessed with the private dollar pattern this._$("valueName"[, replacingValue]);. As Interface does not have a definition for _$, the values cannot be accessed by external objects. Since each prototyped function body's this is set to the values object in function $, you will get exceptions if you call Constructor sibling functions directly; the _$ / $ pattern needs to be followed in prototyped function bodies too. Below sample usage.

var classX1 = new ClassX();
console.log("classX1." + classX1.$("isValAValid", "valid", "invalid"));
console.log("classX1.valA: " + classX1.$("getValA"));
classX1.$("setValA", "v1");
console.log("classX1." + classX1.$("isValAValid", "valid", "invalid"));
var classX2 = new ClassX("v2");
console.log("classX1.valA: " + classX1.$("getValA"));
console.log("classX2.valA: " + classX2.$("getValA"));
//This will throw an exception
//classX1._$("valA");

And the console output.

classX1.valA is invalid.
classX1.valA: undefined
classX1.valA is valid.
classX1.valA: v1
classX2.valA: v2

The _$ / $ pattern allows full privacy of values in fully-prototyped classes. I don't know if I will ever use this, nor if it has flaws, but hey, it was a good puzzle!

JPortillo
  • 543
  • 3
  • 9
0

ES6 WeakMaps

By using a simple pattern based in ES6 WeakMaps is possible to obtain private member variables, reachable from the prototype functions.

Note : The usage of WeakMaps guarantees safety against memory leaks, by letting the Garbage Collector identify and discard unused instances.

// Create a private scope using an Immediately 
// Invoked Function Expression...
let Person = (function() {

    // Create the WeakMap that will hold each  
    // Instance collection's of private data
    let privateData = new WeakMap();
    
    // Declare the Constructor :
    function Person(name) {
        // Insert the private data in the WeakMap,
        // using 'this' as a unique acces Key
        privateData.set(this, { name: name });
    }
    
    // Declare a prototype method 
    Person.prototype.getName = function() {
        // Because 'privateData' is in the same 
        // scope, it's contents can be retrieved...
        // by using  again 'this' , as  the acces key 
        return privateData.get(this).name;
    };

    // return the Constructor
    return Person;
}());

A more detailed explanation of this pattern can be found here

colxi
  • 7,640
  • 2
  • 45
  • 43
-1

You need to change 3 things in your code:

  1. Replace var privateField = "hello" with this.privateField = "hello".
  2. In the prototype replace privateField with this.privateField.
  3. In the non-prototype also replace privateField with this.privateField.

The final code would be the following:

TestClass = function(){
    this.privateField = "hello";
    this.nonProtoHello = function(){alert(this.privateField)};
}

TestClass.prototype.prototypeHello = function(){alert(this.privateField)};

var t = new TestClass();

t.prototypeHello()
A-Sharabiani
  • 17,750
  • 17
  • 113
  • 128
-2

You can use a prototype assignment within the constructor definition.

The variable will be visible to the prototype added method but all the instances of the functions will access the same SHARED variable.

function A()
{
  var sharedVar = 0;
  this.local = "";

  A.prototype.increment = function(lval)
  {    
    if (lval) this.local = lval;    
    alert((++sharedVar) + " while this.p is still " + this.local);
  }
}

var a = new A();
var b = new A();    
a.increment("I belong to a");
b.increment("I belong to b");
a.increment();
b.increment();

I hope this can be usefull.

LPL
  • 16,827
  • 6
  • 51
  • 95