This question already has answers here:
What is the purpose of the var keyword and when should I use it (or omit it)?
(19 answers)
Closed 3 years ago.
I'm trying to create a class like way of accessing objects with public and private functions/variables, but I'm a little confused as to why this simple test code doesn't work.
// Class type object with just one value.
function Play(arg) { // Constructor.
var test = arg;
// Private, as not declared with "this." Obviously more complex in the future.
private_settest = function( val ) {
test = val;
}
// Public.
this.settest = function( val ) {
private_settest(val);
}
this.gettest = function() {
return test;
}
}
var a = new Play(1);
var b = new Play(2);
a.settest(100);
console.log(a.gettest());
console.log(b.gettest());
I'd expect the output to be 1 2 but the actual output is 1 100.
I believe this to be a closure issue, anyone care to explain what I'm missing?
When stepping through this.settest():
The closure value of test is 1 (this is correct).
When stepping into private_settest():
The closure value of test is 2. This is wrong, it should be 1.
On stepping out of private_settest() the closure value is back to 1 again. I guess this is the closure being popped.
Help would be appreciated!
Thanks.
private_settest = function(val) {
test = val;
}
This implicitly defines a global variable private_settest, and when you construct new Play(), the global is overwritten each time, referencing the scope of the last initialized instance of Play, in this case b. That is why the "private" function accesses the second instance's scope, as you have observed. This should be changed to
function private_settest(val) {
test = val;
}
in order to correctly declare a function within each instance's scope.
// Class type object with just one value.
function Play(arg) { // Constructor.
var test = arg;
// Private, as not declared with "this." Obviously more complex in the future.
function private_settest(val) {
test = val;
}
// Public.
this.settest = function(val) {
private_settest(val);
}
this.gettest = function() {
return test;
}
}
var a = new Play(1);
var b = new Play(2);
a.settest(100);
console.log(a.gettest());
console.log(b.gettest());
This produces the expected output 100 2 (not 1 2).
The problem is that private_settest is a global variable. You did not use var (let, const or function) to declare that function variable with local scope. So every time you call the constructor the previous version of that function is overwritten.
When you then call a.setttest, you actually (via the method) call that single global function that modifies the private variable test which really is the private variable of the b instance (the last one that was created).
If you would have used "use strict", you would have received an error message about this.
Related
function emergency() {
var ambulance = 100;
var callAmbulance = function() { alert(ambulance); }
ambulance++;
return callAmbulance;
}
var accident = emergency();
accident(); // alerts 101
I am referring to the variable 'ambulance'.
When I call accident(); it should call emergency() which should use the declared variable 'ambulance' [considering the global scope thing in javascript, still it could set the value to global] but its using old value 101 instead of setting again back to 100 - behaving more like static var.
What's the Explanation?
What you have there is called a closure. It means a function can access variables declared in outer functions (or in the global scope). It retains access even after the 'parent' function has returned. What you need to understand is that you don't get a copy. The changes performed on that variable are visible to your inner function, which in theory means you could have multiple functions sharing access to the same variable.
function f () {
var x = 0;
function a() { x += 1; }
function b() { x += 2; }
function show() { console.log(x); }
return {a:a, b:b, show:show};
}
var funcs = f();
funcs.a();
funcs.b();
funcs.show(); // 3
One thing to be aware of is that a subsequent call to f will create a new scope. This means a new x variable will be created (new a, b, show functions will be created as well).
var newFuncs = f();
newFuncs.a();
newFuncs.show(); // 1
funcs.a();
funcs.show(); // 4
So, how do you get a copy? Create a new scope.
function g () {
var x = 0;
var a;
(function (myLocal) {
a = function () { myLocal += 1; }
}(x));
x += 200;
return a;
}
JS only has pass-by-value so when you call the anonymous function, the xvariable's value will be copied into the myLocal parameter. Since a will always use the myLocal variable, not x, you can be certain that changes performed on the x variable will not affect your a function.
If, by any chance, you're coming from a PHP background you are probably used to do something like
use (&$message)
to allow modifications to be reflected in your function. In JS, this is happening by default.
You are creating a function definition which is not compiled at this time:
var callAmbulance = function() { alert(ambulance); }
And before you are sending it to the called function, you are incrementing the num:
ambulance++;
And then you are sending it to the called function:
return callAmbulance;
But whether you are sending it there or not, it doesn't matter. The below statement executes or compiles the function:
var accident = emergency();
And this takes in the current ambulance value which is 101 after the increment. This is an expected behaviour in creating function but not executing it. Please let me know, if you didn't understand this behaviour. I will explain it more clearly.
I am reading Stoyan Stefanov's "Javascript Patterns". I am confused on the private static member section -- how does it works underlying.
var Gadget = (function () {
var counter = 0;
return function () {
console.log(counter += 1);
};
}());
var g1 = new Gadget(); // logs 1
var g2 = new Gadget(); // logs 2
Why "counter" becomes a static member?
Many thanks in advance!
Gadget is a closure over counter. Whenever you call Gadget, 1 is added to counter.
It might be easier to see if you write the code as
var counter = 0;
var Gadget = function () {
console.log(counter += 1);
};
var g1 = new Gadget(); // logs 1
var g2 = new Gadget(); // logs 2
instead. It should be clear that there is only one counter variable and that its value is increased whenever Gadget is called.
The difference in your code is that it is wrapped in an IIFE, so that counter is not accessible from any other function other than the one returned from the IIFE (which is assigned to Gadget), thus making counter "private".
See also: What is the (function() { } )() construct in JavaScript?
It becomes a static member, because it is not modified outside of the object. It isn't dynamic.
So, it becomes a static member.
In other words, all variables which are used inside an object, and which are not functions and properties, and which is used for internal logic is called static member.
The reason is because the closure for the function returned by the immediate function includes a reference to the same counter for all instances of Gadgets. Things happen like this (roughly):
The immediate function is immediately called (duh).
The function returned will have a reference to 'counter'.
When you call 'new Gadget()' an instance of Gadget is returned.
a. This instance of Gadget is just another way of calling the function that gives an empty object for the 'this' and returns it as well. So g1 and g2 are blank objects.
b. This means all instances will have a reference to 'counter'.
It's private, because nothing outside the object that is created by the immediate execution of the anonymous function whose definition starts on line 1 can access the variable counter.
It's not really static, because, if Gadget is defined in an inner scope, the storage used for Counter could be garbage-collected once Gadget and all of the Gadget objects that it has created have been discarded. But it behaves like static for most purposes when used at the top level.
Confusingly, this code in the more complete example that follows does not do what Stefanov says.
var Gadget = (function () {
var counter = 0, NewGadget;
NewGadget = function () {
counter += 1;
};
NewGadget.prototype.getLastId = function () {
return counter;
};
return NewGadget;
}()); // execute immediately
var iphone = new Gadget();
iphone.getLastId(); // 1
var ipod = new Gadget();
ipod.getLastId(); // 2
var ipad = new Gadget();
ipad.getLastId(); // 3
He writes: "Because we’re incrementing the counter with one for every object, this static property becomes an ID that uniquely identifies each object created with the Gadget constructor.". That's just wrong. There is only one counter, and all of the Gadget objects have a reference to it. The function getLastId() does just what its name suggests: gets the most recently issued id, and not the value of counter when the gadget was created.
So, the above example runs, and produces the results indicated by the comments. But if you try
iphone.getLastId(); // 3
one more time, you get 3 — the current value of counter, not the value when iPhone was created.
To get the effect of each Gadget having a unique id, we can use a fresh variable for each Gadget, like this:
var Gadget = (function () {
var counter = 0, NewGadget;
NewGadget = function () {
counter += 1;
var myId = counter;
this.myUid = function () {
return myId;
};
};
return NewGadget;
}()); // execute immediately
var iphone = new Gadget();
iphone.myUid(); // 1
var ipod = new Gadget();
ipod.myUid(); // 2
var ipad = new Gadget();
ipad.myUid(); // 3
iphone.myUid(); // 1
Note that myId is definitely not static, even though we are using the same pattern as for counter. However, it is private. There is a separate myId for each Gadget, and it's not a property of the Gadget object — it's truly hidden. But the object's myUid function has closed over it.
This question already has answers here:
How can I access local scope dynamically in javascript?
(4 answers)
Closed 9 years ago.
Does JavaScript have a variable for items declared in the function's scope? I would like to access items declared inside a function using an associative array.
For example I can do the following with items at the global scope
var globalVar = "hi";
var myFunction = function () {
alert(window["globalVar"]);
};
But I would like to do a similar thing with variables declared inside a function
var myFunction = function () {
var funcVar = "hi";
alert(func["funcVar"]);
};
I realise doing such a thing isn't necessarily a good thing and I am doing the below instead, but I am still interested if JavaScript has such a variable.
var myFunction = function () {
var func = {funcVar : "hi" };
alert(func["funcVar"]);
};
This question has been asked and answered many times. No, in JavaScript there is no local object containing local variables as properties (in the way that for instance, in browser environments the window object contains global variables as properties).
Depending on what you are trying to accomplish, there are probably many alternative ways to attack it, including the one you are using now.
Duplicate of Javascript: Get access to local variable or variable in closure by its name, How can I access local scope dynamically in javascript?, Javascript local variable declare.
Perhaps you could assign properties to the function object itself, and reference those?
var myFunction = function() {
myFunction.funcVar = 'hi';
alert(myFunction['funcVar']);
};
It is not exactly the answer to your question, but it's the best way I can think of to access local variables as properties of an object. Note that in this method these variables will be visible outside the function in the same manner (that is, looking up the properties of the function).
If you really needed those properties to be hidden, you could hide them within a closure, like so:
var myFunction = function() {
(function hidden() {
hidden.funcVar = 'hi';
alert(hidden['funcVar']);
})();
};
Functions are just special objects that can be invoked. You can set properties of a function, and get them later.
var a = function () {
alert(a.testingVar);
};
a.testingVar = "asdf";
a();
DEMO: http://jsfiddle.net/gEM7W/
Although I don't see a reason/need to do this. You could always use a closure to keep local variables specific to a function. For example:
var a = (function () {
var obj = {
testingVar: "asdf"
};
return function () {
alert(obj.testingVar);
};
})();
a();
DEMO: http://jsfiddle.net/gEM7W/1/
You don't really have associative arrays. You have indexed arrays and you have objects.
In the future, there will be an iterator which will happily traverse both, without any side-effects. At that point, perhaps people will forget the difference.
However, the properties still wouldn't be order-based:
$arr = array(0, 1, "name"=>"Bob", 3);
In another language might get you an array where the keys are: 0, 1, "name", 3
In JS, you'd get 0, 1, 2, "name" (or "name", 0, 1, 2).
So stick with indexed arrays and objects with properties.
That said, you've got multiple options.
var myFunc = function () {
var private_data = {
name : "Bob",
age : 32
};
return {
getName : function () { return private_data.name; /* or private_data["name"] if that's really what your heart longs for */ },
get : function (key) { return private_data[key] || null; },
set : function (key, val) { private_data[key] = val; }
};
};
Now everything is private, and you can access them by property-name, using dot or bracket notation.
If they can be public, and the function is always going to be called the same thing (ie: not a constructor making an instance) then you can attach yourself to the actual function:
var myFunc = function () {
myFunc.name = "Bob";
myFunc["age"] = 32;
return {
get : function (key) { return (myFunc.hasOwnProperty(key)) ? myFunc[key] : null; }
};
};
Downside (or upside) is that myFunc is the public name. As such, these properties are publicly accessible.
Going the first route, you don't even need to declare a variable. You can just use the object you pass into a function.
var myFunc = function (dataObj) {
return {
getName : function () { return dataObj.name; },
setAge : function (val) { dataObj["age"] = val; }
};
};
var bob = myFunc({ name : "Bob" });
bob.setAge(32);
Now everything's private and I didn't even have to declare anything.
Closure keeps the object in play as long as there's a publicly accessible function that's returned, which still has access to that particular instance of the function call.
Once you figure out closures, this becomes a non-issue.
example:
function Foo() {
this.bla = 1;
var blabla = 10;
blablabla = 100;
this.getBlabla = function () {
return blabla; // exposes blabla outside
}
}
foo = new Foo();
original question:
I know that bla will be assigned to every instance of Foo.
What will happen with blabla?
new question:
what I understand now:
this.bla = 1; // will become an attribute of every instance of FOO.
var blabla = 10; // will become a local variable of Foo(**not** an attribute of every instance of FOO), which could be accessed by any instance of FOO only if there's a method like "this.getBlabla".
blablabla = 100; // will define a **new** (or change if exist) global(window) variable.
[Question:] Did i understand correctly?
Any internal-methods you give to this -- ie: this.method = function () {}; while inside of your Foo constructor function, are all going to have a reference to the blahblah which is unique to each instance of a Foo object.
function Wallet () {
var balance = 0;
this.checkBalance = function () { return balance; };
this.depositAmount = function (amount) { balance += amount; };
}
var wallet = new Wallet();
wallet.checkBalance(); // 0
wallet.depositAmount(3);
wallet.checkBalance(); // 3
But it's completely protected from access outside of wallet, unless you return it to somebody, from a privileged function.
wallet.balance; // undefined;
(added bit of interest -- if balance is a string, a number, or a boolean, even if you return it, that won't give people editing rights, or even permanent viewing access -- scalar variables are passed by value, so you're just passing the value of balance at the time -- if, however, balance was an object, a function or an array, they'd have permanent access to modify the crap out of your internal workings)
Note: methods HAVE to be assigned inside of the constructor for this to work.
Prototypes can't access internal variables.
Adding methods later won't give them access to internal variables.
This means that each instance will take up a little more memory, because each has its own copy of the methods, and has its own copy of the vars.
But if what you're doing requires private data, this would be a good way to get it.
In your example blabla is a local variable, so it will go away when the constructor function ends.
If you declare a function inside the constructor, which uses the variable, then the variable will be part of the closure for that function, and survives as long as the function (i.e. normally as long as the object):
function Foo() {
this.bla = 1;
var blabla = 10;
this.getBlabla = function() {
alert(blabla); // still here
}
}
It will become a local (think of 'private') variable within Foo(). Meaning that you can't access it outside of Foo().
function Foo() {
this.bla = 1; // this becomes an extension of Foo()
var blabla = 10; // this becomes a "Local" (sort of like a 'private') variable
}
You could expose it (by returning it) with a Foo method.
function Foo() {
var blabla = 10; // local
this.getBlabla = function () {
return blabla; // exposes blabla outside
}
}
Now outside of Foo():
var FooBar = new Foo();
var what_is_blabla = FooBar.getBlabla(); //what_is_blabla will be 10
jsFiddle demonstration
Variables declared with var inside a function used as a constructor will, like all other variables declared with var inside any function, be visible only during the execution of that function (unless the value is closed over using closures).
In other words, blabla is effectively invisible outside the function:
var foo = new Foo();
console.log(foo.bla); // 1
console.log(foo.blabla); // throws NameError
By defining functions which close over these variables, they become the closest thing JavaScript has to "private" variables:
function Foo() {
this.bla = 1;
var private = 1;
this.increment = function() {
++private;
}
this.getPrivateValue = function() {
return private;
}
}
foo = new Foo();
console.log(foo.bla); // 1
foo.bla = 6; // legal
console.log(foo.bla); // 6
console.log(foo.getPrivateValue()); // 1
// console.log(foo.private); // would throw an error
foo.increment(); // legal
console.log(foo.getPrivateValue()); // 2
// foo.getPrivateValue() = 5; // syntax error. Still can't reassign to private no matter what you try!
That variable is local to the constructor and won't be accessible outside of that scope (be it through this or otherwise), unless it is captured by a closure.
If you don't use the var keyword, "blabla" becomes a global variable. At other points in the code if you also use blabla without var, it will also be global, and you can accidentally change other instances of blabla and introduce unintended bugs in your code. "var" puts the variable in the current scope, so in the case above, it's only accessible to Foo.
blabla can almost be considered a private member of Foo.
See this article from Douglas Crockford.
function getCtr(){
var i = 0;
return function(){
console.log(++i);
}
}
var ctr = getCtr();
ctr();
ctr();
I've been using Javascript from last five years, but this question made me dumb in last interview. I tried everything to my knowledge but can't figure it out.
Can you please help me with the output and reason for it so that I can be better equipped for future interviews if I have one.
var ctr = getCtr();
This calls getCtr(), which initializes i to 0, and stores a reference to the function
function() {
console.log(++i)
}
in ctr. Because that function was created in the scope of getCtr(), the variable i is still accessible in the scope of the function stored in ctr.
The first call to
ctr()
executes console.log(++i) which has a preincrement on i, so it prints out 1. The second call executes the same code, with the same preincrement, and prints out 2.
DISCLAIMER: Not a javascript developer. Forgive me if I've made an error or used some unpreferred wording.
So the code you posted outputs 1 2. Yet the code:
function getCtr(){
var i = 0;
return function(){
console.log(++i);
}
}
getCtr()();
getCtr()();
outputs only 1 1!
The difference is that if you save a reference to getCtr() by using the var ctr = getCtr();, you create what is called a closure.
So the difference between calling getCtr()() and ctr() is that ctr has i defined in its scope, and that scope is saved thanks to var ctr = getCtr();. Because the reference is saved, the function inside of ctr is able to always act on the same variable.
run this:
var m=0;
var d=0;
alert(m++ +":"+ ++d);
and you get "0:1"
IF it were me asking in an interview, the difference in where the ++ is is what I would be after :)
http://jsfiddle.net/MarkSchultheiss/S5nJk/
Closures
The return statement in that function saves i. So when var i = 0; is only called var ctr = getCtr();. Then ctr becomes the returned function:
function () {
console.log(++i)
}
and the variable ctr has i in the scope of the outer function, getCtr() and the return function is in the scope of getCtr() as well.
okay, getCtr is a function that returns an other function.
It also contains a var called "i" which is set to 0.
"i" is also available in the scope of the returned function.
the preincrement of "i" before logging it to the console causes that it increases by 1 every time the returned function, which is stored in "ctr", is called.
When executed, function getCtr returns an inner anonymous function.
This function is now referenced by variable ctr
Because the anonymous function was created inside getCtr it will have access to getCtr private scope object, which contains variable 'i'. This is known as a closure.
var ctr = getCtr()
Every time the anonymous function is executed it pre-increments i, and writes in in the console.
ctr()
Lets break it down using terms you might know from classical inheritance based OOP languages:
// In javascript functions are first-class objects
// This function is being used like a class would be in Java
function getCtr(){
// You can think of this as a private variable of the getCtr "class"
var i = 0;
// Because it is returned, this is effectively a public method of getCtr
return function(){
// Which increments i and then prints it.
console.log(++i);
}
}
// This makes the variable ctrl an instance of getCtr.
var ctr = getCtr();
// This calls ctr's only public method.
ctr();
ctr();
So the output would be "1, 2".
What this question is meant to do is test if you understand Javascript's prototypal inheritance, ability to have anonymous functions, and closures.
A clarified version of that could that would do the same thing would be:
var myProtoype = function() {
var privateVariable = 0;
var privateMethod = function () {
privateVariable++;
console.log(privateVariable);
}
return {
publicMethod: privateMethod
};
}
var myInstance = new myPrototype();
myInstance.publicMethod();
myInstance.publicMethod();
That function is a Javascript Module. You can have a good reading about it on Javascript: the Good Parts, which is a great book and I highly recommend. A Module uses Javascript closures to create private variables and if assigned to a var the var will retain it's vars each time it's called instead of redefining the vars.
A module works like this
function moduleName(privateVar1){
var privateVar1;
var privateVar2;
return {
exposedFunction1: function (var1) {
// Do stuff... using private vars
return something;
},
exposedFunction2: function (var1, var2) {
// Do stuff...
return something;
}
}
}
var moduleInstance = moduleName(privateVar1);
moduleInstance.exposedFunction(var1);