i came across following example in my training guide for HTML5/javascript/css
I don't understand why the private variables from the method are added as private variables in underlying object/namespace ns.
(function () {
this.myApp = this.myApp || {};
var ns = this.myApp;
var vehicleCount = 5;
var vehicles = new Array();
ns.Car = function () { }
ns.Truck = function () { }
var repair = {
description: 'changed spark plugs',
cost: 100
};
}());
this is the explanation the book gives:
An IIFE (pronounced iffy) is an anonymous function expression that has a set of parentheses at the end of it, which indicates that you want to execute the function. The anonymous
function expression is wrapped in parentheses to tell the JavaScript interpreter that the function isn’t only being defined; it’s also being executed when the file is loaded.
In this IIFE, the first line creates the myApp namespace if it doesn’t already exist, which
represents the singleton object that is used as the namespace. Next, an ns variable (for namespace) is created as an alias to the namespace to save typing within the IIFE, so ns can
be used in place of this.myApp. After that, the private members of the namespace are defined
by using the var keyword. Car and Truck are public, so they are prefixed with ns.
I would expect following code if they wanted to make these properties privates of the myApp 'namespace'
(function () {
this.myApp = this.myApp ||
{
var ns = this.myApp;
var vehicleCount = 5;
var vehicles = new Array();
var repair = {
description: 'changed spark plugs',
cost: 100
};
};
ns.Car = function () { }
ns.Truck = function () { }
}());
They are private because they are defined in the closure and totally encapsulated as local variables inside the closure.
ns becomes a local variable too. There is no reference back to scope outside the closure.
This is a self calling closure and the scope of the definitions is similar to defining local variables in a "normal" function.
Related
I have this code and wondering how can we access properties and method of IIFE
var app = (function () {
function app() {
this.name = 'fasf';
}
app.prototype.greeting = function () {
this.a = 'hello world';
console.log(name);
window.alert('hello world');
};
app.prototype.sayhello = function () {
var j = 't';
console.log(this.a);
};
return app;
}());
also about this piece of code
var t = (function greet(name){
name = name || 'enter your name'
console.log('Hello ' + name);
})();
With the code you have, you can just do this:
// create an instance of the app object
var a = new app();
// call methods on it
a.greeting();
a.sayhello();
Your IIFE returns the internal app constructor function and then assigns that to a variable named app. So you can then do new app() to create an instance of that object. Once you create an instance of that object, you can then call any of the methods on the prototype.
In your second IIFE, nothing is returned from the IIFE so t is undefined.
The IIFE itself does not have properties and methods. That's just an immediately invoked function expression. In your first one, it returns a constructor function which is then assigned to a variable so that variable can be used to create objects with that constructor function. There are no properties or methods of the IIFE itself.
The way the IIFE pattern works is that you use local variables for the stuff you want to keep private. Local variables are are only visible inside the function they were defined in they cannot be read or written from anywhere else in the program.
If you want to expose things inside the IIFE outside the IIFE one way to do it is via the return value of the immediately-invoked function:
var stuff = (function(){
// These variables and functions are not
// visible from the outside:
var myvar1 = "Hello";
var myvar2 = "World";
var func1(){
return myvar1 + " " + myvar2;
}
// But we can return a record that contains a
// reference to our private functions, making them
// visible outside this block.
return {
thefunc: func1
}
}());
//Now we can call the "thefunc" function we exported
console.log( stuff.thefunc() );
I made sure to not repeat any variable names to avoid confusion.
In your first example, there isn't much of a point to using the IIFE pattern since there are no local variables that you are making private. You could have just defined the app function outside the IIFE and it would have worked the same.
The second case could have been written more clearly by putting the function in a separate line:
function greet(name){
name = name || 'enter your name'
console.log('Hello ' + name);
}
var t = greet();
Not only is it a bit weird to immediately invoke a named function but in your particular example, the "default argument value" pattern suggests that this function was designed to be called multiple times, sometimes passing the "name" argument and sometimes not passing it (in which case it defaults to the "enter your name" string.
When using IIFE pattern (closure) you usually keep local variables and function private as properly mentions by hugomg's answer.
In case you need to selectively make public some specific property you could consider using "The Revealing Module Pattern" instead, more info here.
Below a simple example showing this pattern:
var app = (function () {
var privateVar = 'hello world';
function sayhelloPrivate() {
console.log(privateVar);
}
function sayhelloPublic() {
console.log(privateVar);
}
// reveal public pointers to
// private functions and properties
return {
sayhello : sayhelloPublic
};
})();
app.sayhello();
//app.sayhelloPrivate(); this will not work as function is private and not visible outside module
Usually, you can create private variables by using var x instead of this.x in defining function and then you create objects like so: var o = new SomeClass(). However, I need something like PHP class with static methods (object with private variables without any further assigning). Same like defining class and then creating the object from it, but directly defining the object, while still maintaining private variables. Is it possible?
EDIT:
Normal private variable definition:
function SomeClass() {
var x = '1dg5456awd32tr5';
this.getX = function() {return private;}
}
var o = new SomeClass();
o.getX();
How to save that x variable without using the function?
I don't know if I have understood correctly your question but you can take advantage of the javascript scope behaviour by creating something like this: http://jsfiddle.net/2R8yY/
var Order = (function(){
var company = 'ACME';
var klassOrder = function(){};
klassOrder.getCompany = function(){
return company;
}
return klassOrder;
})();
console.log(Order.getCompany()); // -> ACME
Privacy of the local variable scope is not restricted to constructor functions. However, you always need to invoke a function to create a "private" scope - even if that function is not assigned to any identifier.
You seem to be looking for Immediately-Executed Function Expressions or the module pattern.
var o = (function() {
var x = '1dg5456awd32tr5';
return {getX: function() {return private;}};
}());
o.getX();
Just so you know, in JavaScript functions are objects.
Because JavaScript scope is functional, it becomes easy to restrict member variable access by declaring local variables in a function's scope. Most commonly, the Facade Pattern or Module Pattern are used.
Are you looking for something like this?
var SomeClass = (function(myPrivateThingy) {
var privateInt = myPrivateThingy;
return function() {
this.getInt = function() { return privateInt; }
}
}());
var instance = new SomeClass(99);
// instance.getInt() === 99
Can we reuse var name without overwriting its details in JavaScript.Taking below example of augmented module pattern
<script>
var Module = (function () {
// Module object
var module = {},
privateVariable = "Hello World";
function privateMethod() {
// ...
}
module.publicProperty = "Foobar";
module.publicMethod = function () {
//console.log( privateVariable );
return privateVariable;
};
return module;
})();
//Defining same name MODULE var again
var Module = (function (my) {
var newvar = 999;
my.anotherMethod = function () {
return newvar;
};
return my;
}(Module));
alert(Module.publicMethod());
//How this upper MODULE property is accessible ? Should be hide by
//next same name MODULE var?**
alert(Module.anotherMethod());
</script>
Above code is running perfectly fine and adding one more anotherMethod under MODULE but how it is still accessing initial module property. Defining var with same name (MODULE) shoudn't overwrite (remove) the upper module.
Defining var with same name (MODULE) shoudn't overwrite (remove) the upper module.
Yes, it should.
The global scope (or the function if you are inside a function) is scanned for var statements. Since you have two identical ones, the second one is ignored. MODULE is created in the global scope.
Then you run a function and then assign its return value to the MODULE.
Then you run another function, passing the current value of MODULE as an argument to it, then you assign the return value to MODULE.
A reference to the object created at var my = {} still exists in the scope of the second function, but the only reference to it from the global scope has been overwritten.
Is there a way to create private global variables in JavaScript? I have tried looking around, and I keep bumping into talk of constructors - which don't seem too global.
Thanks
Not sure what your use case is. I'll assume you have a js script file containing some functions and variables and you want to expose some of those globally, but keep the rest private to your script file. You can achieve this with a closure. Basically you create a function that you execute immediately. Inside the function you place your original code. You then export the functions you need into the global scope.
// Define a function, evaluate it inside of parenthesis
// and execute immediately.
(function(export) {
var myPrivateVariable = 10;
function myPrivateFunction(param) {
return param + myPrivateVariable;
}
export.myGlobalFunction = function(someNumber) {
return myPrivateFunction(someNumber);
};
})(this); // The *this* keyword points to *window* which
// is *the* global scope (global object) in a web browser
// Here it is a parameter - the *export* variable inside the function.
// This is executed in the global scope
myGlobalFunction(2); // yields 12 (i.e. 2 + 10)
myPrivateVariable; // Error, doesn't exist in the global scope
myPrivateFunction(2) // Error, doesn't exist in the global scope
To answer your question, no, that is not possible as there are no access modifiers in javascript. A variable declared in global scope is accessible to any function.
As pointed out in the comments to this answer, you can create objects which have private members. Crockford has a page on private members in Javascript. He uses the following code to illustrate his point:
function Container(param) {
// private method
function dec() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
this.member = param;
var secret = 3;
var that = this;
// privileged method
this.service = function () {
return dec() ? that.member : null;
};
}
In the above example, param, secret, and that are all private in that they are not accessible from the outside. To be more clear, these variables can only be accessed by privileged or private methods, the difference being that privileged methods can be called from any instance of the object. As is suggested in the comments, this is achievable by using closures.
Quoting from Crockford for a quick explanation on closures, but you can find plenty of related questions.
What this means is that an inner function always has access to the
vars and parameters of its outer function, even after the outer
function has returned.
in order to have private members. you need to use closures.
following code help you understanding the concept.
function CustomArray () {
this.array = [];
var privateData = 'default data';
this.getPrivateData = function () {
return privateData;
};
this.setPrivateData = function (data) {
privateData = data;
};
};
CustomArray.prototype.push = function (data) {
this.array.push(data);
};
CustomArray.prototype.unshift = function (data) {
this.array.unshift(data);
};
CustomArray.prototype.pop = function () {
this.array.pop();
};
CustomArray.prototype.shift = function () {
this.array.shift();
};
CustomArray.prototype.print = function () {
console.log(this.array.join(','));
};
var array = new CustomArray();
array.push(10);
array.push(20);
array.push(30);
array.push(5);
array.unshift(3);
array.unshift(2);
array.unshift(1);
array.unshift(0);
array.pop();
array.shift();
array.print();
console.log(array.getPrivateData());// default data
array.setPrivateData('am new private data');
console.log(array.getPrivateData());//am new private data
For my web application, I am creating a namespace in JavaScript like so:
var com = {example: {}};
com.example.func1 = function(args) { ... }
com.example.func2 = function(args) { ... }
com.example.func3 = function(args) { ... }
I also want to create "private" (I know this doesn't exist in JS) namespace variables but am not sure what's the best design pattern to use.
Would it be:
com.example._var1 = null;
Or would the design pattern be something else?
Douglas Crockford popularized so called Module Pattern where you can create objects with "private" variables:
myModule = function () {
//"private" variable:
var myPrivateVar = "I can be accessed only from within myModule."
return {
myPublicProperty: "I'm accessible as myModule.myPublicProperty"
}
};
}(); // the parens here cause the anonymous function to execute and return
But as you said Javascript doesn't truly have private variables and I think this is somewhat of a cludge, which break other things. Just try to inherit from that class, for example.
Closures are frequently used like this to simulate private variables:
var com = {
example: (function() {
var that = {};
// This variable will be captured in the closure and
// inaccessible from outside, but will be accessible
// from all closures defined in this one.
var privateVar1;
that.func1 = function(args) { ... };
that.func2 = function(args) { ... } ;
return that;
})()
};
After 7 years this might come quite late, but I think this might be useful for other programmers with a similar problem.
A few days ago I came up with the following function:
{
let id = 0; // declaring with let, so that id is not available from outside of this scope
var getId = function () { // declaring its accessor method as var so it is actually available from outside this scope
id++;
console.log('Returning ID: ', id);
return id;
}
}
This might only be useful if you are in a global scope and want to declare a variable that is not accessible from anywhere except your function that sets the value of id one up and returns its value.