What happens with "var" variables inside a JavaScript Constructor? - javascript

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.

Related

Javascript public variable/methods

I have JavaScript code as below;
var foo = (function() {
//Private vars
var a = 1;
return {
//Public vars/methods
a: a,
changeVar: function () {
a = 2;
}
}
})();
Now I am not sure how the syntax for public vars/methods works ?
Could you please corelate how just "returning" the vars/methods makes them as public ?
Thank you.
The value of the variable foo is actually the value returned by this function. Notice on the last line, the (), indicating that this function is evaluated immediately. By evaluating a function and assigning its return value to a variable, you are able to hide variables inside a local (function) scope, such that they are not accessible outside that scope. Only members on the returned object are accessible, but because any functions inside form a closure with their outer scope, you can still use local (hidden) variables.
An example of this would be to hide some local state and only allow access to it through a method:
var foo = (function() {
//Private vars
var a = 1;
return {
//Public methods
getVar: function () {
return a;
},
setVar: function (val) {
a = val;
}
}
})();
Okay, you've returned an object in the anonymous function, which means that the object is assigned to foo. So you can access the object's properties like foo.a or foo.changeVar, but you can continue to let the private variables exist, within the function's scope. Can't help much without a more specific question.

referring to the current function without using its name/arguments.callee

I have done a fair amount of research but have not been able to find any answers, to what seems like a simple question:
I want to associate a property with a function (to use as a static variable in this function), like so:
function foo() {
if (!foo.counter) {
foo.counter = 1;
}
else {
foo.counter++
}
// rest of the function code goes here...
}
If I change the name of the function later, I don't want to have to change references to it inside function definition.
So, is there a way to refer to the currently executing function? (other than arguments.callee which is now deprecated). A keyword like thisFunction?
If not, what is the reason for not having something like this?
I do not know of an identifier or keyword like thisFunction (besides arguments.callee) that JavaScript exposes, but one way to achieve the same effect is to name the function foo in a closure, and return foo from that closure. That way you can always use the name foo within foo to refer to itself, regardless of what variable it's assigned to by your program:
var fn = (function() {
function foo() {
if (!foo.counter) {
foo.counter = 1;
}
else {
foo.counter++
}
// rest of the function code goes here...
}
return foo;
})();
function foo() {
if (typeof foo.counter=="undefined") {
foo.counter = 1;
}
else {
foo.counter++
}
return foo;
}
var x = new foo();
alert(x.counter); //1
var y = new foo();
alert(x.counter); //2
If you don't need to refer to the counter outside of the function, this will work. Instead of setting a variable of the function itself, you define a variable outside of the function and let the function modify that instead. Every time you call makeFoo, it makes a new variable x and returns a function using x. Every time you call the returned function, it still refers to the same x created by makeFoo. Additionally, this entirely encapsulates the variable, ensuring that almost nothing outside of the returned function can change it (it definitely won't be changed by most things outside of the returned function, but there is enough funky javascript reflection that I can't guarantee that nothing will change it). Certainly, moving the function between variables won't affect the counter (ie x=makeFoo();y=x;x=null;).
function makeFoo() {
var x=0;
return function () {
x++;
return x;
}
}
//different counters
x=makeFoo();
y=makeFoo();
x();//returns 1
y();//returns 1
x();//returns 2
y();//returns 2
//same counter
x=makeFoo();
y=x;
x();//returns 1
y();//returns 2
x();//returns 3
y();//returns 4

OOP. Calling methods from within methods

How do I call class methods from functions within the class? My code is:
var myExtension = {
init: function() {
// Call onPageLoad
},
onPageLoad: function() {
// Do something
},
}
I've tried ...
onPageLoad();
... from within the init method but it's saying it's not defined.
I'm not having much luck with google because I don't understand the syntax used. All the JS OOP examples I find online are in a different format. I'm using the format Mozilla use for extension development.
The object the current method was invoked on is available via the special variable this. Any time you call a method on an object, this will refer, within the method, to the object.
var myExtension = {
init: function() {
this.onPageLoad();
},
onPageLoad: function() {
// Do something
},
};
this always refers to the calling object rather than the object the function is defined on or is a property of.
value = 'global';
var ob0 = {
value: 'foo',
val: function() {
return this.value;
},
},
ob1 = {value: 'bar'},
ob2 = {value: 'baz'};
ob0.val(); // 'foo'
ob1.val = ob0.foo;
ob1.val(); // 'bar'
ob0.val.call(ob2); // 'baz'
var val = ob0.val;
val(); // 'global'
In the last case, val is executed as a free function (a function that isn't bound to an object, i.e. not a method), in which case this takes on the value of the global object (which is window in web browsers) within the execution of val. Global variables are actually properties of the global object, hence val() returns 'global' (the value of the global variable named value). Since global variables are actually properties of the global object, you can view free functions as actually being methods of the global object. From this viewpoint, the last two lines (when executed in global scope) are equivalent to:
window.val = ob0.val;
window.val();
This viewpoint doesn't exactly match the reality of scoping, though you'll only notice the difference within functions. In a function, window.val = ... will create a global while var val won't.
value = 'global';
var ob0 = {
value: 'foo',
val: function() {
return this.value;
},
};
function lcl() {
var val = ob0.val; // doesn't set a global named `val`
return val(); // 'global'
}
lcl(); // 'global'
val(); // error; nothing named 'val'
function glbl() {
window.val = ob0.val; // sets a global named `val`
return window.val(); // 'global'
}
glbl(); // 'global'
val(); // 'global'
See MDN's reference page for more on the call method used above. For more on the this variable, see "JavaScript “this” keyword" and "How does “this” keyword work within a JavaScript object literal?"
Assuming that you have called init like this:
myExtension.init();
then it should be:
init: function() {
// before
this.onPageLoad();
// after
}
But in Javascript functions are not actually bound to objects and you can call any function on any other object, like this:
myExtension.init.call(anotherObject); // or
myExtension.init.apply(anotherObject);
In this example this within init would be anotherObject, which doesn't have onPageLoad defined. If you want to support this kind of usage you'll have to manually reference the initial object:
init: function() {
// before
myExtension.onPageLoad();
// after
}
In Javascript you need to explicitly mention the this
this.onPageLoad()
The same is also true for other member variables (remember that in Javascript methods are just member variables that happen to be functions)
this.memberVariable
Have you considered a closure, instead?
For example:
var myExtension = ( function() {
var me = {};
var private_thingy = "abcDEFG123";
var onPageLoad = function() {
// do page loading business
alert( private_thingy );
}
me.onPageLoad = onPageLoad;
var init = function() {
onPageLoad();
}
me.init = init;
return me;
})();
///////////////
myExtension.private_thingy = "DIDDLED!";
// will NOT modify the private_thingy declared within the closure
myExtension.init(); // will work fine.
Anything you define within the closure is available within the closure at all times, and when implemented carefully will yield private members not accessible to users of the object. Only members that you explicitly export - e.g., the me.xxx = xxx lines - are publicly available.
Thus, when onPageLoad executes, "abcDEFG123" will be displayed in the alert, not "DIDDLED!". Users of the object can modify properties using the dot operator until the cows come home; what's not made public by the closure, however, can never be modified: even if the user reassigns a function on the public interface, calls to the private function from within the closure will always point to the function defined within the closure.
The important part: it unties you from the constant use of this (unless you really want to use it; save your fingers for more important typing!).
Give it a shot. And have a look at Javascript: The Good Parts by Crockford.

When I declare a variable inside a function, which object is it a property of?

So when I declare a variable outside the scope of any function, it becomes a property of the window object. But what about when I declare a variable inside the scope of a function? For example, in the following code I can treat x as a property of window, i.e., window.x, but what about y? Is it ever the property of an object?
var x = "asdf1";
function test() {
var y = "asdf2";
}
test();
It becomes a property of the Variable object associated with the function call. In practice, this is the same thing as the function call's Activation object.
I don't believe that the Variable object is accessible to running JavaScript code, though; it's more of an implementation detail than something you can take advantage of.
Access all local variables is a related question here on SO.
In order to declare a JS variable a property of an object you need to either use the new Object(); method or the {} syntax.
var variableName = new Object();
var variableName = {myFirstProperty:1,myNextProperty:'hi',etc};
Then you can assign child objects or properties to said variable object
variableName.aPropertyNameIMadeUp = 'hello';
variableName.aChildObjectNameIMadeUp = new Object();
As such the new variable object is associated with a method if it is within the method call.
Cheers
See following example (I have copy from other question-answer) very nice:
// a globally-scoped variable
var a=1;
// global scope
function one(){
alert(a);
}
// local scope
function two(a){
alert(a);
}
// local scope again
function three(){
var a = 3;
alert(a);
}
// Intermediate: no such thing as block scope in javascript
function four(){
if(true){
var a=4;
}
alert(a); // alerts '4', not the global value of '1'
}
// Intermediate: object properties
function Five(){
this.a = 5;
}
// Advanced: closure
var six = function(){
var foo = 6;
return function(){
// javascript "closure" means I have access to foo in here,
// because it is defined in the function in which I was defined.
alert(foo);
}
}()
// Advanced: prototype-based scope resolution
function Seven(){
this.a = 7;
}
// [object].prototype.property loses to [object].property in the scope chain
Seven.prototype.a = -1; // won't get reached, because 'a' is set in the constructor above.
Seven.prototype.b = 8; // Will get reached, even though 'b' is NOT set in the constructor.
// These will print 1-8
one();
two(2);
three();
four();
alert(new Five().a);
six();
alert(new Seven().a);
alert(new Seven().b);

Dynamically attach a function to grant access to private variables

I'm trying to assign a callback dynamically to an Object of mine, I can't seem to figure out a way to do this while granting this function access to private variables. I've listed the relavant code below with comments where I ran into walls.
Object Factory
function makeObj ( o ) {
function F() {}
F.prototype = o;
return new F();
}
Module
var MODULE = (function(){
var myMod = {},
privateVar = "I'm private";
return myMod;
})();
Various Attempts
myMod.someDynamicFunc = function someDynamicFunc(){
//privateVar === undefined;
alert( privateVar );
}
myMod.someDynamicFunc();
myMod.prototype.someDynamicFunc = function someDynamicFunc(){
//ERROR: Cannot set property 'someDynamicFunc' of undefined
alert(privateVar);
}
myMod.someDynamicFunc();
In this attempt I tried making a setter in the module object... to no avail.
var MODULE = (function(){
var myMod = {},
privateVar = "I'm private";
myMod.setDynamicFunction = function ( func ){
if(func !== undefined && typeof func === "function"){
//Uncaught TypeError:
// Cannot read property 'dynamicFunction' of undefined
myMod.prototype.dynamicFunction = func;
//also tried myMod.dynamicFunction = func;
}
}
return myMod;
})();
var myModule = makeObject( MODULE );
myModule.setDynamicFunction(function(){
alert(privateVar);
});
myModule.dynamicFunction();
Am I just using JavaScript wrong? I'd really like to be able to assign callbacks after the object is initiated. Is this possible?
You can't access the private variable via a callback function set dynamically (since it can't be a closure if it's attached later), but you can set up a system by which you would be able to access the variable:
var MODULE = (function(){
var myMod = {},
privateVar = "I'm private";
myMod.callback = function(fn) {fn(privateVar);};
return myMod;
})();
var someDynamicFunc = function(param) {alert(param);};
myMod.callback(someDynamicFunc);
Of course, this makes it not really private, since anyone could do this. I don't see how it would be possible at all for you to have a "private" variable that you access via dynamically attached functions, without allowing anyone else's dynamically attached functions to have the same privilege (thus making it not really private).
I guess you did not really understand exactly how closures work.
Closures mean that scopes always have access to the outer scope they were defined in.
function Counter(start) {
var count = start;
return {
increment: function() { // has access to the outer scope
count++;
},
get: function() {
return count;
}
}
}
var foo = new Counter(4);
foo.increment();
foo.get(); // 5
The above example returns two closures, both the function increment as well as get keep a reference to the count variable defined in the constructor.
One cannot access count from the outside, the only way to interact with it is via the two "closured" functions.
Remember, closures work by keeping a reference to their outer scopes, so the following does not work:
var foo = new Counter(4);
foo.hack = function() { // is not getting defined in the same scope that the original count was
count = 1337;
};
This will not change the variable count that's inside of Counter since foo.hack was not defined in that scope, instead, it will create or override the global variable count.

Categories