I am trying to make sense and understand when to use private and when to use privileged methods in JavaScript. According to this post: Private Members in JavaScript, private members of an object can be accessed and modified both by private methods and privileged methods. When writing getter methods (for the private members), would you use a private or privileged method? Why? For accessors (methods that modify private members) would you use private or privileged methods? Why? What is the standard technique used in this cases?
And lastly, what is the difference in using a private vs privileged method to access a private variable (apart from the fact that the private method cannot be called from outside).
function ClassB(given)
{
var myVar = given;
function _get ()
{
return myVar;
};
this.get = function ()
{
myVar = myVar + 3;
return myVar;
};
}
When you are designing your objects you need to make a decision to start. Do you care about exposing the internals of the object to the outside world?
If you don't care, then you should really be adding all of your methods to the prototype of the object, and all your instance variable to this in your constructor function. This approach may not be desirable in some situations. This is where the privileged methods come in, as well as the usage of closures to mimic private methods.
When you create a privileged method, it has access to private and public members of the object as you've noted. The big difference between creating a privileged method and a public method on the prototype is that the privileged method is created with every instance of the object, whereas the public method on the prototype is only created once. If you have many privileged methods and you are creating A LOT of instances of your objects, you could see how this may not be desirable when it comes to memory usage.
I assume you are looking to hide some of your internal functionality from the outside world, so you will need to make use of privileged methods. For all your getters/setters, you will need to define them as privileged and add them to this (otherwise there isn't much point in creating getter/setters if you plan on leaving them private):
function SomeClass() {
// Private member
var _privateMember = 1;
// Public variable
this.publicMember = 1;
// Privileged getter method
this.getPrivateMember = function() {
return _privateMember;
};
// Privileged setter method
this.setPrivateMember = function(newVal) {
_privateMember = newVal;
};
// Private method that has access to '_privateMember' and 'this'
var _privateMethod = function() {
// Modify private member
_privateMember = 2;
// Modify public member
this.publicMember = 1;
// Do some other fancy processing privately
};
this.doSomethingAwesome = function() {
// Do some stuff here...
// Call your private method maybe?
_privateMethod();
};
}
// Public methods on prototype do not have access to private methods in your constructor
SomeClass.prototype.publicMethod = function() {
// Cannot access `_privateMember`
this.publicMember = 2; // Does have access to 'this'
};
As for your last question, about using a private vs. privileged method for modifying some private members... As you've said, you wouldn't be able to access it from the outside world which means it would be pretty useless unless you are adding other functionality to your private getter method, and exposing it to the outside world via a privileged method. If you do a lot of heavy lifting inside the constructor of your object, this could be a valid reason to create a reusable getter/setter method, but that really depends on your use case.
If this did not answer what your question was, or if you would like any other specific explanation about something feel free to ask.
Related
What is mean 'private variable' in javascript?
There isn`t 'private variable' declare in javascript.
so we usually have used '_' or closure.
In this Point, I was curious 'closure'.
I got example from another site.
function createAnimal(name, job) {
// "Private" variables here
let _name = name;
let _job = job;
// Public variables here
return {
// Getter Methods
getName() {
return _name;
},
getJob() {
return _job;
},
// Setter Methods
setName(newName) {
_name = newName;
},
setJob(newJob) {
_job = newJob;
}
};
}
Above example
we can change _name 'private variable' of setName.
Reault
'private variable' mean that we can`t access variable? or constant?
I hope, this may help you:
Private members are made by the constructor. Ordinary vars and
parameters of the constructor become the private members.
function Container(param) {
this.member = param;
var secret = 3;
var that = this;
}
This constructor makes three private instance variables: param,
secret, and that. They are attached to the object, but they are not
accessible to the outside, nor are they accessible to the object's own
public methods. They are accessible to private methods. Private
methods are inner functions of the constructor.
function Container(param) {
function dec() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
this.member = param;
var secret = 3;
var that = this;
}
The private method dec examines the secret instance variable. If it is
greater than zero, it decrements secret and returns true. Otherwise it
returns false. It can be used to make this object limited to three
uses.
By convention, we make a private that variable. This is used to make
the object available to the private methods. This is a workaround for
an error in the ECMAScript Language Specification which causes this to
be set incorrectly for inner functions.
Private methods cannot be called by public methods. To make private
methods useful, we need to introduce a privileged method.
Reference: Read more
Private variables are hidden, and therefore can't be accessed directly. For instance, you would not be able to call animal._name = "Rover".
Instead, you're expected to call a function that encapsulates the variable. In your example, you would instead call animal.setName("Rover"). So, these variables aren't necessarily constant, but they can only be changed by calling special methods that change them internally.
Programmers like private variables sometimes, because there are situations where manipulating a variable directly could cause issues.
For instance:
function createLogger() {
let _numMessagesLogged = 0;
return {
logMessage(message) {
console.log(message);
_numMessagesLogged += 1;
},
getNumMessagesLogged() {
return _numMessagesLogged;
},
};
}
In this example, we increment a counter (_numMessagesLogged) every time a message is logged. If the counter were public, someone could set logger._numMessagesLogged = -12345, which doesn't make any sense. Instead, we want the variable to be private, so that we know for sure that the number of messages logged increases only when we log something-- that is, it increases only when we call logMessage().
Closures are just one way of implementing private members via JavaScript. There are other ways to do this as well, but the method isn't as important as the underlying concept.
You may be interested in reading more about encapsulation.
I am following this link https://addyosmani.com/resources/essentialjsdesignpatterns/book/ to understand design patterns in Javascript I understood constructor pattern , module pattern and module revealing pattern , now in Singleton pattern I have two doubts which are following :
1) I know c++ and I am learning JavaScript now, so I understand singleton pattern allows you only one instance of the class but in this book it's mentioned "In JavaScript, Singletons serve as a shared resource namespace which isolate implementation code from the global namespace so as to provide a single point of access for functions." What does it mean ???
2)
var mySingleton = (function () {
// Instance stores a reference to the Singleton
var instance;
function init() {
// Singleton
// Private methods and variables
function privateMethod(){
console.log( "I am private" );
}
var privateVariable = "Im also private";
var privateRandomNumber = Math.random();
return {
// Public methods and variables
publicMethod: function () {
console.log( "The public can see me!" );
},
publicProperty: "I am also public",
getRandomNumber: function() {
return privateRandomNumber;
}
};
};
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function () {
if ( !instance ) {
instance = init();
}
return instance;
}
};
})();
var singleA = mySingleton.getInstance();
var singleB = mySingleton.getInstance();
My doubt is when we call mySingleton.getInstance(); won't be the value "instance" undefined again, as it is a local variable and everytime we call the getInstance method it should set the instance value as undefined and hence
if ( !instance )
should pass always and give a new instance but I don'y understand how it's working here. Kindly explain.
var mySingleton is a IIFE function and this returns you an object (or in module revealing pattern term, exposes property of getInstance)
Every time mySingleton is referred in the code, the content inside it executes every time. Hence resetting instance variable. Note, init method also returns an object with 3 properties indicating that these are exposable too (can be made public and even the private variables can be made public by processing them in a public function. Pretty much the C++/Java concepts).
In the end, we use this init() and tag it to getInstance
Hence when I do
var singleA = mySingleton.getInstance();
var singleB = mySingleton.getInstance();
I can access the (selectively)"exposed" properties singleA.publicMethod()
Flow: singleA [refers to] getInstance() [exposed through] mySingleton [and] getInstance() [refers to] init() [which exposes] publicMethod, publicProperty and getRandomNumber [which indirectly gives you access to] privateRandomNumber
Doubt #1
Serve as a shared resource namespace and hide code implementation.
It is sharing the private properties and methods of init method globally whilst you are in a namespace 1 level above init.
Private methods are hidden and not exposed.
Doubt #2
Every time mySingleton is referred, instance is re-declared.
Hope this helps
1) This means that only variable var mySingleton is now accessible from global namespace. It exposes single public method getInstance which returns one and only one instance of a class (code responsible for managing private reference to this instance is hidden from outside scope).
2) No, var instance is defined in "outer" scope. (not in scope of getInstance function)
In javascript Object is a reference data type which means the instance returned here is same.
var singleA = mySingleton.getInstance();
var singleB = mySingleton.getInstance();
singleA === singleB // > true
and the fact that we are able to access the instance variable in getInstance function of mySingleton is due to closure's
I want to be able to create an object in Javascript that has public methods which can access the object's private members. However, I've heard that there's overhead in declaring public methods every time an object is created, so I'd prefer to avoid that overhead. So, for example, this code would do what I want:
function createMyObject(parameter) {
var that = {};
var privateVariable,
privateMethod = function () { return 1; };
that.publicVariable = 0;
that.publicMethod = function () {
privateVariable = privateMethod();
}
return that;
}
But everytime someone calls createMyObject, it has to create functions to set the public methods. If instead I do this:
function MyClass(parameter) {
var privateVariable,
privateMethod = function () { return 1; };
this.publicVariable = 0;
}
MyClass.prototype.publicMethod = function () {};
Here, I can avoid having to create new functions to set public methods everytime an object is constructed, but those public methods can't access the object's private members.
Is there some way to avoid the overhead of having to create new functions for public methods everytime an object is constructed, but also be able to let them have access to private members?
No, you can't.
A public method which is able to access private variables, is called privileged method.
From Private Members in JavaScript, by Douglas Crockford:
A privileged method is able to access the private variables and
methods, and is itself accessible to the public methods and the
outside. It is possible to delete or replace a privileged method, but
it is not possible to alter it, or to force it to give up its secrets.
Privileged methods are assigned with this within the constructor.
Then, you can't declare privileged methods using the prototype.
Using new Javascript features you can have truly private members. Basically you can use WeakMap to hide your members.
This is supported in Firefox and behind the "Experimental Javascript" flag in Chromium.
var MyClass = (function(){
var privmap = new WeakMap; // This holds our private members. Keep it secret.
function MyClass(){
var priv = {};
privmap.set(this, priv); // Add your private object for this instance.
this.notsec = "Anyone can access this!";
priv.secret = "Only code in this closure can see this!";
}
MyClass.prototype.secret = function MyClass_secret() {
var priv = privmap.get(this); // Get our private object.
return priv.secret; // Retrieve.
}
return MyClass;
})();
var o = new MyClass;
console.log(o.secret()); //-> Only code in this closure can see this!
By adding one line to the beginning of every function you can return your private object. I like to call it priv so that public members go on this and private on priv, nice and consistent.
This has the nice advantage that you only have a single instance of every method, instead of creating a closure for each instance.
So I'm using this pretty standard jquery plugin pattern whereby you can grab an api after applying the jquery function to a specific instance.
This API is essentially a javascript object with a bunch of methods and data.
So I wanted to essentially create some private internal methods for the object only to manipulate data etc, which just doesn't need to be available as part of the API.
So I tried this:
// API returned with new $.TranslationUI(options, container)
$.TranslationUI = function (options, container) {
// private function?
function monkey(){
console.log("blah blah blah");
}
// extend the default settings with the options object passed
this.settings = $.extend({},$.TranslationUI.defaultSettings,options);
// set a reference for the container dom element
this.container = container;
// call the init function
this.init();
};
The problem I'm running into is that init can't call that function "monkey". I'm not understanding the explanation behind why it can't. Is it because init is a prototype method?($.TranslationUI's prototype is extended with a bunch of methods including init elsewhere in the code)
$.extend($.TranslationUI, {
prototype: {
init : function(){
// doesn't work
monkey();
// editing flag
this.editing = false;
// init event delegates here for
// languagepicker
$(this.settings.languageSelector, this.container).bind("click", {self: this}, this.selectLanguage);
}
}
});
Any explanations would be helpful. Would love other thoughts on creating private methods with this model too.
These particular functions don't HAVE to be in prototype, and I don't NEED private methods protected from being used externally, but I want to know how should I have that requirement in the future.
// Edited based on Matthew's comment
So I tried moving the prototype definition based on Matthew's comment. This seems to work now, but still not sure if this is the correct way to be doing this. Thoughts? Obviously it would be cleaner if I move the prototype object into a separate area
$.TranslationUI = function (options, container) {
function monkey(){
console.log("blah blah blah");
}
// extend the default settings with the options object passed
this.settings = $.extend({},$.TranslationUI.defaultSettings,options);
// set a reference for the container dom element
this.container = container;
$.extend($.TranslationUI.prototype,
{
init : function(){
monkey();
// editing flag
this.editing = false;
// init event delegates here for
// languagepicker
$(this.settings.languageSelector, this.container).bind("click", {self: this}, this.selectLanguage);
}
}
);
// call the init function
this.init();
};
So while this works, the crappy part is that I'm re-initing prototype every time that constructor runs. I'm sure that's not efficient. But not sure how else to have the prototype methods have access to private functions/variables of a certain instance.
The error is because monkey is not defined in the scope you're calling $.extend from.
Alright. So found an answer on stackoverflow, confirmed by Crockford's site.
javascript - accessing private member variables from prototype-defined functions
Essentially, you can't really get access to private functions from the prototype methods. You can via 'privileged' functions, which in turn call private variables and functions, but then you are basically creating a crapload of getters and setters, which might just be doubled in your prototype "public" methods.
So its kind of a lot of work, especially if your stuff doesn't TRULY need to be private.
Have a look at my answer and some of the others here:
call function inside a nested jquery plugin
Are there any downsides to using a JavaScript "class" with this pattern?
var FooClass = function()
{
var private = "a private variable";
this.public = "a public variable";
var privatefn = function() { ... };
this.publicfn = function() { ... };
};
var foo = new FooClass();
foo.public = "bar";
foo.publicfn();
What you're doing in your example isn't the "class" pattern people think of in JS -- typically people are thinking of the more "normal" class model of Java/C#/C++/etc which can be faked with libraries.
Instead your example is actually fairly normal and good JS design, but for completeness i'll discuss behaviour differences you'll see between the private and public "members" you have
var private = "a private variable";
this.public = "a public variable";
Accessing private from within any of your functions will be quite a lot faster than accessing public because the location of private can be determined reasonably well just with a static lookup by the JS engine. Attempts to access public require a lookup, most modern JS engines perform a degree of lookup caching, but it is still more expensive than a simple scoped var access.
var privatefn = function() { ... };
this.publicfn = function() { ... };
The same lookup rules apply to these functions as with the above variable accesses, the only real difference (in your example) is that if your functions are called, say privatefn() vs this.publicfn(), privatefn will always get the global object for this. But also if someone does
f = foo.publicfn;
f();
Then the call to f will have the global object as this but it will be able to modify the private variable.
The more normal way to do public functions however (which resolves the detached public function modifying private members issue) is to put public functions on the prototype, eg.
Foo.prototype.publicfn = function() { ... }
Which forces public functions to not modify private information -- there are some times where this isn't an option, but it's good practice as it also reduces memory use slightly, take:
function Foo1() {
this.f = function(){ return "foo" };
}
vs
function Foo2() {
}
Foo2.prototype.f = function(){ return "foo" };
In Foo1 you have a copy of the function object for every instance of Foo1 (not all the emory, just the object, eg. new Foo1().f !== new Foo2().f) whereas in Foo2 there is only a single function object.
That's good so far, but there's another access level you've left out.
this.publicfn is really a priveleged method as it has access to private members and functions.
To add methods which are public but not priveleged, modify the prototype as follows:
FooClass.prototype.reallypublicfn = function () { ... };
note that this method does not have access to private members of FooClass but it is accessible through any instance of FooClass.
Another way of accomplishing this is returning these methods from the constructor
var FooClass = function()
{
var private = "a private variable";
this.public = "a public variable";
var privatefn = function() { ... };
this.publicfn = function() { ... };
return {
reallypublicfn: function () { ...}
}
};
var foo = new FooClass();
foo.public = "bar";
foo.publicfn();
Basically, these methods of data hiding help you adhere to traditional OOP techniques. Generally speaking, improving data-hiding and encapsulation in your classes is a good thing. Ensuring low coupling makes it much easier to change things down the road, so publicly exposing as little as possible is really to your benefit.
See https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript for a simple overview and http://www.crockford.com/javascript/private.html for details on how to accomplish these things.
The main downside is that you'll wind up with a copy of publicfn for each instance of FooClass. If you'll be creating a lot of FooClass objects, it would be more efficient to
write
FooClass.prototype.publicfn = function() { ... };
It depends on your needs and relative performance. Javascript isn't the most type-safe language and isn't very strong with regards to member visibility. Traditionally you can have "private", "public privileged", and "public" visibility within a Javascript type.
You can declare private and public privileged members using:
function FooClass()
{
var privateVar = 1;
function privateFn()
{
return privateVar; // etc...
}
this.publicVar = 2;
this.publicFn = function()
{
return privateFn();
}
}
This example uses a function closure, which consists of a function declaration that includes values from the scope where the function is defined. This is acceptable when member visibility is necessary but can lead to overhead. The JavaScript interpreter cannot reuse the privateFn or publicFn definitions for every instantiation since they refer to variables or functions in the outer scope. As a result every instance of FooClass results in additional storage space for privateFn and publicFn. If the type is uses infrequently or in moderation the performance penalty is neglegible. If the type is used very often in the page, or if the page is more of an "AJAX" style where memory isn't freed as frequently since the page is not unloaded then the penalty can be more visible.
An alternative approach is to use prototype members. These are unprivleged public members. Since Javascript is not entirely type-safe and is relatively easy to modify after it's loaded, type safety and member visibility aren't as reliable for controlling access to type internals. For performance reasons, some frameworks like ASP.NET Ajax instead using member naming to infer visibility rules. For example, the same type in ASP.NET Ajax might look like:
function FooClass2()
{
this._privateVar = 1;
this.publicVar = 2;
}
FooClass2.prototype =
{
_privateFn : function()
{
return this._privateVar;
},
publicFn : function()
{
return this._privateFn();
}
}
FooClass2.registerClass("FooClass2");
In this case the private scoped members are private in name only, the "_" prefix is considered to mean a private member variable. It has the downside of preventing the member from being truly private, but the upside of allowing in-memory patching of the object. The other main benefit is that all functions are created once by the interpreter and engine and reused over and over for the type. The "this" keyword then refers to the instance of the type even though the function reference itself is the same.
One way to see the difference in action is to try this with both types (if you don't have ASP.NET Ajax, you can ignore the last line in FooClass2 that calls registerClass())
var fooA = new FooClass(), fooB = new FooClass();
alert(fooA.publicFn===fooB.publicFn); // false
var foo2A = new FooClass2(), foo2B = new FooClass2();
alert(foo2A.publicFn===foo2B.publicFn); // true
So its a matter of type safety and member visibility vs. performance and the ability to patch in memory
Also, if I may mention something useful to this - With prototype you are able to add additional methods later on in the code to extend the function from an extern scope. As a tiny benefit, the whole body with all the methods won't be rendered every time, hence it speeds up compiling performances. If you have all the declared methods inside the function already, this slightly would take more time to render. So, my advice, apply these later only when they become relevent in the current code.
Example:
// inside
function fn(arg) {
this.val = arg;
fn.prototype.getVal =()=> {
console.log(this.val);
}
}
var func = new fn('value');
func.getVal();
// declare extern methods
function fn2(arg) {
this.val = arg;
}
fn2.prototype.getVal =()=> {
console.log(this.val);
}
var func2 = new fn2('value');
func2.getVal();