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();
}();
Related
I decided to create a funcB function that I call from funcA. I want all variables from funcA to be available in the funcB so func B can change that variables.
How to modify the code below so it meets my requirements? I doubt passing all variables it the only possible and the best way.
function funcB(){
alert(var1);//how to make it alert 5
alert(var20);//how to make it alert 50
}
function funcA(){
var var1=5;
...
var var20=50;
funcB();
}
var obj = {
one : "A",
two : "B",
fnA : function() {
this.fnB(); // without fnB method result will be displayed as A B, with fnB as C D
console.log(this.one + " " + this.two);
},
fnB : function() {
this.one = "C";
this.two = "D";
}
};
obj.fnA();
this keyword refers to obj object
You can define object with properties and methods inside it. With methods all the variables can be manipulated as you wish, from this example with fnB I'm changing values of properties which are displayed from fnA method
JSFiddle
One way is to drop the var keyword:
function funcB(){
alert(var1);//how to make it alert 5
alert(var20);//how to make it alert 50
}
function funcA(){
var1 = 5;
var20 = 50;
funcB();
}
This will expose them to the global scope so funcB can access them. Notice you can also create the varaibles in the global scope itself, with the var keyword, but both methods will ultimately have the same effect.
Note:
This may not work if there is already a var1 or var20 in the global scope. In such case, it will modify the global value and may result in unwanted errors.
This method is not preferred for official code, and is bad practice Reason
This is not possible as when you declare a variable with the var keyword, they are scoped to the function in which they are declared.
If you avoid the var keyword, they are instead defined as a global variable. This is deemed very bad practice.
I would recommend you read up on javascript coding patterns, particularly the module pattern.
For example:
var myNamespace = (function () {
var foo, bar;
return {
func1: function() {
foo = "baz";
console.log(foo);
},
func2: function (input) {
foo = input;
console.log(foo);
}
};
})();
Usage:
myNamespace.func1();
// "baz"
myNamespace.func2("hello");
// "hello"
I am writing a userscript for some site.
I need to access inner variable in a function. For example, in following code i need to access
"private property" b of object c
function a(){
var b;
//assignment to b and other stuff
};
var c=new a();
I CANNOT CHANGE THE SITE'S CODE, I ONLY CAN CHANGE BORWSER EXTENSION SCRIPTISH AND WRITE A USERSCRIPT.
My browser is the latest firefox.
I need to gain access even if i would have to change Scriptish.
You can't access to your inner variable of your function, you should make it global variable to get it from outside.
var b;
function a(){
b=1;
//assignment to b and other stuff
};
var c=new a();
document.write(c.b);
and the output will be 1.
In your code b isn't a private variable, but a local variable. And after execution of var c=new a(); b doesn't exist anymore. Thus, you can't access it.
But if you use closures, everything changes:
function a(){
var b;
//assignment to b and other stuff
this.revealB = function() {
return b;
}
};
var c = new a();
alert(c.revealB());
Here b is still a local variable, but its lifetime is affected by closure, thus it's still alive when we call revealB.
It is quite simple thing to do, and it is great for inheritance applications:
You simply return whatever you want, and maybe return it through methods, later reuse it in other functions and build up on it.
Example follows:
function a(){
var b;
//assignment to b and other stuff
return b;
};
// or
function a(){
var b, result;
//assignment to b and other stuff
returnInitial: function() {
return b;
}
// other stuff with b
return result;
};
Later you can use so called "parasitic inheritance" and initiate this whole function inside other function using all local variables and adding new methods, like so:
var a function() {
var b, result;
//assignment to b and other stuff
returnInitial: function() {
return b;
}
// other stuff with b
return result;
}
var extendedA function() {
var base = new a;
var b = a.returnInitial();
a.addToB = function (c) {
var sum = c + a.returnInitial();
return sum;
}
}
So you can now get
var smt = new extendA();
var c = 12; //some number
var sumBC = extendA.addToB(c);
For all there is to these great practices, I recommend yutube search for doug crockford's lectures on js objects handling.
Note that you need to use new since dynamic object handling which javascript uses can crash your original object if you do not initialize a fresh instance.
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();
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.
First question
var obj = function(){
var a = 0;
this.b = 0;
}
Is there any difference in behaviour of a and b?
Second question
var x = 'a';
var f1 = function(x){ alert(x) }
var f2 = new Function('alert('+x+')')
Is there any difference in behaviour of f1 and f2
Question 1
var obj = function() {
var a = 0;
this.b = 0;
}
Within the function, you'll be able to access both variables, but in the case of
var x = new obj();
... you'll be able to access x.b, but not x.a.
Question 2
As your question is written at the moment, it is a syntax error. The following will work:
var x = 'a';
var f1 = function(x){ alert(x) }
var f2 = new Function('alert('+x+')')
... but that would be the same thing as writing:
var x = 'a';
var f1 = function(x){ alert(x) }
var f2 = new Function('alert(a)')
The difference here is obvious. f1 disregards the global variable x and alerts whatever is passed to it, while f2 also disregards the global variable x, and tries to look for a global variable a. This is probably not what you're trying to ask about.
What you probably want is something like this:
var x = 'a';
var f1 = function(){ alert(x) }
var f2 = new Function('alert(x)')
... or this:
var f1 = function(x){ alert(x) }
var f2 = new Function('x', 'alert(x)')
The difference between the two alternatives above is that the first always uses the global variable x, while the second never uses any global variable. The difference between f1 and f2, internally, in both examples, is none at all.
These are two ways of generating the exact same result. The only reason you'd ever want to use the f2 approach would be when generating the code in some dynamic manner that require string input for its definition. In general, try to avoid this practice.
var obj = function() { // function expression, while obj is created before head
// it's only assigned the anonymous function at runtime
var a = 0; // variable local to the scope of this function
this.b = 0; // sets a property on 'this'
}
Now what this is depends on how you're calling the function.
Also note the difference between function statements and expressions.
var x = 'a'; // string a, woah!
var f1 = function(x){ alert(x) } // another anonymous function expression
// Does not work
// 1. it's "Function"
// 2. It gets evaluated in the global scope (since it uses eval)
// 3. It searches for 'a' in the global scope
var f2 = new function('alert('+x+')') // function constructor
In short, never use the Function constructor, it will never inherit local scope and therefore you can't use closures with it etc.
First question:
var obj = function() {
var a = 0;
this.b = 0;
}
instance = new obj();
instance.showA = function() {
alert("this.a = " + this.a);
}
instance.showB = function() {
alert("this.b = " + this.b);
}
instance.showA(); // output undefined - local scope only, not even to methods.
instance.showB(); // output 0 - accessible in method
Paste this in your Firebug console and run to see the output and behavior for yourself.
Second question:
var f2 = new function('alert('+x+')');
This throws a syntax error in Firebug because the f should be capitalized. This is a case where a function is defined inside a string and evaluated. Here is a good example:
var x = 'a=3';
var f2 = new Function('alert('+x+')');
f2(); // outputs 3 because the x passed into the variable is evaluated and becomes nested inside the quotes prior to the alert command being fired.
Here is what the substitution process looks like:
1: x = "a=3";
2: 'alert(' + x + ')');
3: 'alert(' + 'a=3' + ')'); // x replaced with a=3
4: 'alert(a=3)';
5: 'alert(3);'
When function runs, alert(3) is fired. This can be used to execute other JavaScript pulled down from a remote server, although extreme care should be used for security reasons. When evaluating code that is nested in quotes, it helps to start from the inside and work your way up to the top level context. More information on dealing with nested quotes or embedded code can be found here: http://blog.opensourceopportunities.com/2007/10/nested-nested-quotes.html
Question 1: homework on scoping of variables (var b is local to the enclosing {} (local to the function in this case).
Question 2: Instead of using the Function constructor you could use eval? http://www.w3schools.com/jsref/jsref_eval.asp , as in
eval 'alert('+x+')';
Second question is VERY interesting. Only benchmarks can say the truth.
http://jsperf.com/function-vs-function/
http://jsperf.com/function-vs-function/1..8
http://jsperf.com/function-vs-constructor-vs-eval
http://jsperf.com/function-vs-constructor-vs-eval/1..5
It looks they are almost equal? I can see in modern browsers each variant is optimized enough
BUT BE AWARE OF RECREATING THE FUNCTION IN A LOOP!
http://jsperf.com/function-vs-function/2
Any wise comments?