javascript pass parameter values to same named outer scope variables - javascript

var a,b,c;
function abc(a,b,c){
console.log("a is"+ a + ", b is"+ b + ", c is"+ c);
}
a; // undefined
b; // undefined
c; // undefined
I will be passing through strings a,b,c, but would like to also be able to access them once they are passed through the function.
So if I call abc("d","e","f"), I'd like that function to run using those three strings, but afterwards, outside of its own scope, I'd also like to be able to use a="d", b="e", and f="f".
Could someone explain how this is done? I think that even though they are declared outside of the function, the fact that it's the same name is throwing me off.
I remember something in PHP about adding & before the parameter...
Thanks!

I'm not sure what you're asking here, but it works just out of the box like you want it.
Since ECMAscript has function scope, the variables a, b and c will get locally resolved within the function context of abc(). The outer declarations of those
variable names (lets call them free variables), will never get accessed because the lookup process will find those names first within its *own context, resolve them and stop there.
If you just want to set those free variables which are part of a parent context, you probably should rename your formal parameters for convenience and then pass over the values
function abc(some, other, name) {
a = some;
b = other;
c = name;
}
Hopefully that parent scope where a, b and c are declared is not the global scope. That is very correctly still considered bad practice and karma, for a couple of reasons.

Best practice would be to give the inner variables different names, e.g. by prefixing them with 'inner' or the initials of the function name. Not only can you then simply assign the values to the outer variables with a simple a = innerA, but it also makes your code more readable.

You can't use the variables in the outer scope if they're masked by function parameters with the same name.
You could, if they were named properties of a variable that is in the outer scope. In browsers, global variables are actually just properties of the window variable:
var myobj = {};
function abc(a, b, c) {
myobj.a = a;
myobj.b = b;
myobj.c = c;
}
// you can now use those values

Firstly, I think you mean:
var a, b, c;
function abc(_a, _b, _c) {
a = _a;
b = _b;
c = _c;
}
abc(1, 2, 3);
console.log("a is"+ a + ", b is"+ b + ", c is"+ c); // 1, 2, 3
Given that said, I think this approach is not a good practise. Please organise them within a closure or a namespace. For example, here is an acceptable design pattern :
(function(g) {
var _SomeClass = function(a, b, c) {
this.a = a;
this.b = b;
this.c = c;
}
_SomeClass.prototype = {
printValues: function() {
console.log(this.a, this.b, this.c);
},
doSomething: function() {
// do something here
},
_privateMethod: function() {
// should not be called from outside the closure
}
}
g.SomeClass = _SomeClass;
})(window);
var myClass = new SomeClass(1, 2, 3);
myClass.printValues();

Related

How can I prevent Node.js from garbage collecting (GC) a critical variable

The property of a variable is purged in Node.js during garbage collection. However, I don't want this to happen. I have found solutions for it, such as saving a variable to a database or file. However, I don't like that approach. I just need a critical section or critical variable protected from garbage collection.
For instance, with the following code:
function a() {
var b;
}
c = new a();
How can I protect variable c from garbage collection?
After time goes by, c.b or c is deleted... In my case, c.b is deleted...
Please help me... I know my english is very poor, but I need your assistance so much.
One thing to note, in your code b and d are not properties on a. They are local variables to the scope inside of the function a, which are not used, thus get cleaned up.
If you change it to:
function a() {
this.b = 1;
this.d = 2;
}
var c = new a();
console.log(c.b) //1
console.log(c.d) //2
You can then reference c.b and c.d and as long as you have a reference to c, it should not get collected. Also if you have it as var b, d; you cannot reference those from outside of the function.
compare to:
function a() {
var b = 1;
var d = 2;
}
var c = new a();
console.log(c.b) //undefined
console.log(c.d) //undefined
I'm not sure, but you don't specify any scope for variable c. This would get c into the most upper scope and prevent it from getting removed by the garbage collector.
You can define c in current scope:
let c;
function doSomething() {
c = {b: 1, d: 2};
}
doSomething();

Explaining variable scope in JavaScript

This is simple, but I cannot understand why it does not work.
var a = function() {
console.log(c); // "10" is expecting, but it is not defined
};
var b = function() {
var c = 10; // local variable, but it is accessibly for b(), I think
a();
}();
Why is variable c not defined? And how can I resolve this problem without passing c into b() as an argument?
this way:
var c = 0;
var a = function() {
console.log(c); // "10" is expecting, but it is not defined
};
var b = function() {
c = 10; // local variable, but it is accessibly for b(), I think
a();
}();
The question is better viewed from the other side. Why would it be defined? a wouldn't really be so reusable with a comment saying "NOTE: You can only run this function if you have a var c declared in the encompassing function". That's just not very discoverable, and means it's very hard to track how long a certain naming scope is used.
A feature of JavaScript that may do what you desire is "closures". This is when you declare an entire function inside of another; it's very handy for callbacks when you don't feel the second function deserves its own naming and place in the code structure.
What will happen here is that the language will automatically see that it needs c (already declared) inside of the function you're declaring, and so it preserves an internal reference to it, associated with the callbackFunction variable. So, you can still refer to it in there.
var b = function() {
var c = 10; // local variable, but it is accessibly for b(), I think
var callbackFunction = function() {
console.log(c);
};
// optionally, place c in a setTimeout, ajax callback, etc.
callbackFunction();
}();
The function a has a new scope in which c isn't defined. You could define var c = 0; outside of a or pass c as argument to a.
you forgot to add parameter to function a
var a = function(c) {
console.log(c); // "10" is expecting, but it is not defined
};
var b = function() {
var c = 10; // local variable, but it is accessibly for b(), I think
a(c);
}();
function inherits parent scope where it was declared, not where it was called. All functions inherit window scope, so you can just make variable c global.
var a = function() {
console.log(c); // "10" is expecting, but it is not defined
};
var b = function() {
c = 10; // local variable, but it is accessibly for b(), I think
a();
}();

What is the purpose using a named function when assigning to a variable in JavaScript?

I recently came across this pattern in the source for https://github.com/yeoman/generator-webapp:
AppGenerator.prototype.packageJSON = function packageJSON() {
this.template('_package.json', 'package.json');
};
What's the purpose of giving the function the name "packageJSON" when you're going to assign it to a variable or object property anyways? I've always used anonymous functions in similar cases.
For debugging purposes. If you use a named function you can see that name in the call stack trace in your favorite dev tools. Otherwise you'd see anonymous function.
That's called a named function expression (or NFE) and it makes the debugging process much easier.
An important detail to remember is that this name is only available in
the scope of a newly-defined function; specs mandate that an
identifier should not be available to an enclosing scope:
var f = function foo(){
return typeof foo; // "foo" is available in this inner scope
};
// `foo` is never visible "outside"
typeof foo; // "undefined"
f(); // "function"
As others says, for debugging purposes mainly. But not only that. For instance, you can rely on the fact that in function's body, you can access to the function itself using the name you set. To give a silly example:
var sum = function (a, b) {
if (a < 3)
return sum(3 + a, b);
return a + b;
}
sum(1, 2) // 3;
But let's see what happens now:
var aSum = sum;
sum = null;
aSum(1, 3); // TypeError: sum is not a function
Naming the function, will cover that use case:
var sum = function sum(a, b) {
if (a < 3)
return sum(3 + a, b);
return a + b;
}
sum(1, 2) // 6
var aSum = sum;
sum = null;
aSum(1, 2) // 6
That's because in the body of the function, the name of the function is always referring to it, and is not taken from another scope, like the first example.

In a function, what is happening with/without using var before the variable?

Here is my code
var a = this.innerHTML;
var b = 'blababibbaib';
if(a !== b)
{
c = a;
return this.innerHTML = b;
}
else
{
return this.innerHTML = c;
}
and with the var
var a = this.innerHTML;
var b = 'blababibbaib';
if(a !== b)
{
var c = a; // here with the var it makes c undefined :-(
return this.innerHTML = b;
}
else
{
return this.innerHTML = c;
}
The reason I was doing this is because I wanted a function for an onclick event that would change back and forth between the original and var b. Just for fun really.
But I don't understand why when you add the var in front of the c variable it makes it undefined once you click through it. Will someone illuminate me?
I'm guessing it has something to do with variable scope when used in functions????
Thanks in advance :-)
Edit:
Okay, I did this to declare it with var, but I'm still not sure why exactly.
Outside the function I added an if check for c before declaring it
if(!c) var c = '';
But like I said, I would still like to hear whats going on and why Thanks :-)
Edit 2: Thanks everybody, reading about hoisting now.
I was getting confused I think, it seems even you don't need to check for c either. Thought might matter...oh well. Thanks again
What is happening in the second example is equivalent to this:
var a = this.innerHTML;
var b = 'blababibbaib';
var c; // all "var" are hoisted to the top of a function body
if(a !== b)
{
c = a;
return this.innerHTML = b;
}
else
{
// local c variable not set yet - undefined
return this.innerHTML = c;
}
Obviously c is undefined here, since it is output only when it is not set. I suspect what you actually want is:
var a; //This persists after the function is invoked
myelement.onclick = function () {
if (!a) { // Only save the value if it isn't already set
a = this.innerHTML;
}
var b = 'blababibbaib';
if (this.innerHTML == b) {
return this.innerHTML = a;
} else {
return this.innerHTML = b;
}
};
You can see it here.
As far as the first snippet is concerned, it works because the value of c is not local to the function, and persists after its invocation. When you assign or refer to a variable in a function body without declaring it using the var keyword, it automatically refers to a property of window with the same name. Consider the following:
window.c = "Hello, world.";
//Note how there is no local c variable;
//the c here refers to window.c
function test1(){
alert(c);
}
//There is a c variable local to the
//function, so the value alerted is not the value of window.c
function test2(){
var c;
alert(c);
}
test1(); // alerts "Hello, world."
test2(); // alerts "undefined"
In the first snippet, you are changing the value of window.c to this.innerHTML whenever the HTML is not "blababibbaib". When the value is "blababibbaib", you are relying on window.c to reset the element's innerHTML.
You might want to read up on hoisting in JS, as well as implicit globals.
Without the var prefix c becomes a global variable and is available in all scopes.
JavaScript only has function scope thus using var scopes your variable to the most recent function context (or global scope if not declared inside a function).
That's probably, because your variable c, exist only in if statement, so you need to do:
var a = this.innerHTML;
var b = 'blababibbaib';
var c;
if(a !== b)
{
var c = a; // here with the var it makes c undefined :-(
return this.innerHTML = b;
}
else
{
return this.innerHTML = c;
}
With the first code, since you have not used var c, which makes c a global variable.
Following your logic, c will only get set in the if, never the else. So if c is a global variable that exists outside the function, it can maintain "state" between calls. If you declare it with var inside, then it becomes local to each call.
When you don't allocate new memory to a variable within a particular scope, it defaults to using a variable matching that name up the parent scope chain.
Using the 'var' keyword triggers the memory allocation in the current scope, and otherwise will assign the value as a member of window, which is persistent across calls to your function.
This is a little confusing, but should be really easy to remember when you know. When you omit the var keyword while defining the variable, the variable gets attached to the global scope. This is generally an undesired in well-written programs because you have variables floating around which should've been disposed off when the scope expired.
In your case, when you add the var c = a within the if statement, even though javascript automatically hoists the variable to the function scope -- i.e. the variable name would exist -- but it won't assign it a value until it encounters the var c = a line of code. By default, any variable not assigned a value gets the undefined state.
When you've omitted the var, c is promoted to the global scope, and the global state keeps that value of c as long as you're on the page. Therefore, coming back into the else clause you'll get a valid -- but old -- value of c.
As a rule of thumb, variables defined without var aren't a good practice, and you should define all variables that you use near the start of the function to avoid any confusion with hoisting or such especially if you're from a C/C++/Java background.

Variable is "undefined" when used in a different method?

I have this code for the setup of an object:
myObj.prototype.__init = function(a, b, c){
this.a = a;
this.b = b;
this.c = c;
}
And then in another function I want to use the a I setup in the __init method:
myObj.prototype.myFunc = function(){
var data = parse(a);
//...
}
The problem is that a is undefined. I also tried this.a and it results undefined too. The funny thing is that a console.log(myO) after doing a var myO = new myObj(); and myO.__init(myA, myB, myC); prints the object with the field a initialized. How do I access then a inside that function of my object?
Thanks
EDIT: This is the call to myFunc:
someVar = new tccHandler.myObj();
someVar.__init(myA, myB, myC);
someVar.myFunc();
I suspect it should be parse(this.a).
Remember that properties of this are not in the lookup-chain for identifiers [read: variables] by default; only lexical variables and properties of "the global object" (i.e. window) are.
a is a variable in the function __init (as a function parameter), where the object it names is assigned to the property this.a, but a is not a variable of the function myFunc. Each function introduces it's own lexical scope.
Happy coding!
In normal javascript, you would do:
myObj = function(a,b,c) {
this.a = a;
this.b = b;
this.c = c;
}
Demo:
> var x = new myObj(1,2,3);
> x.a;
1

Categories