I am wondering if this way is correct:
var userInput = confirm('roll die?');
var rollDie = function() {
while(userInput) {
var dieSide = Math.floor(Math.random() * 6);
document.write('you rolled a ' + (dieSide + 1));
userInput = false;
}
}
rollDie(userInput);
Or do I need to write var rollDie = function(userInput) {
Javascript works with scopes. You call the function 'rollDie' from a scope where 'userInput' is a variable. The function 'rollDie' has its own scope. In your example there's no variable 'userInput' in the scope of the function rollDie. There for javascript is looking for the variable in an outer scope and find the variable. So your program is working but the code is not good code.
because you call the function rollDie with the parameter 'userInput' you should add 'userInput' as param to the function rollDie. var rollDie = function(userInput) {} It is always better the give a function all the params the function needs to execute. This prefents problems with the 'this' scope in javascript when you call the function in an other context and make it easier to refactor your code.
twoStrars is quicker :)
You should understand the difference and then choose for yourself.
Basically, you have these two patterns:
x as global variable:
var x = 1;
var f = function() {
console.log('x in f:', x);
x = 2;
}
console.log('x before f:', x);
f();
console.log('x after f:', x);
and x as argument:
var x = 1;
var f = function(x) {
console.log('x in f:', x);
x = 2;
}
console.log('x before f:', x);
f(x);
console.log('x after f:', x);
There two main differences:
if f uses a global variable, it is going to modify the global variable, whereas if it works with an argument, it does not affect any variables visible outside, i.e. the first code writes x after f: 2, whereas the second writes x after f: 1
if f uses a global variable, then it becomes less convenient to pass it different values. With an argument, you don't even need a global variable, you can call f(1); f(2); f(3456);. With global vaiables, you would accomplish the same with var x=1; f(); x=2; f(); x=3456; f();.
Instead of going more into details, I'll give you a link: Why are global variables evil?
Anyway, there are cases when global variables are good! I would make a global variable for a value which is constant and used by multiple functions (var GRAVITY = 9.81; or var BASE_URL = "https://stackoverflow.com/";)
This line:
rollDie(userInput);
…means you're trying to pass a value into your rollDie() method. This isn't strictly necessary because you have this variable declared globally:
var userInput = confirm('roll die?');
So, you could pass nothing in if you wanted, but if you want to write much cleaner code it's preferable to avoid having these global variables around as much as you can. The way you've written it – passing in a value to your function – is much nicer, so it's better to write var rollDie = function(userInput) {.
Related
What is the difference between a direct argument and a global, in a function?
By direct argument I mean to an argument we pass directly in function routine (instead in the subroutine based on parameters in the routine). For example:
var x = (0, 1)=>{ // Routine.
// Subroutine.
}; // Routine.
x();
By a global parameter I mean to variables defined directly in the function's routine (edit, at least in JavaScript this is formally called global parameters. For example:
var x = (x=0, y=1)=>{ // Routine.
// Subroutine.
} // Routine.
x();
How will you explain the difference between direct arguments to globals?
Sorry if something was inaccurate in terminology.
This makes no sense at all :
let x = (0, 1)=>{ // Routine.
// Subroutine.
}; // Routine.
x();
beacuse if you want to have predefined variables you just declare it in your function scope like so:
let x = () => {
const one = 1;
const two = 2;
}
A global variable is variable which you can access from anywhere in the program. In javascript you have the global object window. Global variables are in general bad practice. It would work like this:
one = 1;
two = 2;
let x = () => {
// e.g. add one and two and return
return window.one + window.two;
}
x();
Notice the that both variables declared don't have a const, let or var.
Since ES2015 you can supply default values for arguments:
let x = (x = 1, y = 2) => {
// do stuff:
}
x();
// or
x(2, 3);
In this case if you call the function without declaring the parameters within the function call it will automatically be 1 for x and 2 for y
direct arguments are not supported in javascript. Execute following code and you will see.
let x = (0, 1)=>{ // Routine.
// Subroutine.
}; // Routine.
x();
var inner = function() { console.log(x); }
// test 1
(function(cb) { var x = 123; cb(); })(inner);
// test 2
(function(cb) { var x = 123; cb.apply(this); })(inner);
// test 3
(function(cb) { var x = 123; cb.bind(this)(); })(inner);
// test 4
(function(cb) { cb.bind({x: 123})(); })(inner);
All tests result in:
ReferenceError: x is not defined
Do someone know how it is possible to access 'x' as a local variable inside the callback?
Fact: when you do var inner = function() { console.log(x); } in your first line, x is not defined. Why? Because, inside your inner function, there's no local declaration of x (which would be done with var x = something). The runtime will then look up in the next scope, that is the global scope. There isn't, also, a declaration of x, so x is also not defined there.
The only places where there is a variable called x are inside each one of your 4 IIFEs following. But inside the IIFEs, each x is a different variable, in a different scope. So, if what you want is to console.log() the x defined inside each IIFE, you are taking the wrong approach.
Keep in mind that, when you define inner, you are capturing the environment inside the function's closure. It means that, whatever value could x have there (in the declaration of the function), would be the available value to the x variable later, when the inner function would be used. The fact that your x there is not defined is only an accessory, and is not what is causing the undesired behavior.
So, what happens is that when you call your inner function inside any of your IIFEs, the x referred to inside the inner function declaration is a captured value of what x had as a value when the function was defined, not the value that x has now in the scope where the function is currently being called. This is what is called lexical scope.
To solve this, you would have to pass the value that you want to console.log() inside the inner function as a parameter to the inner function, as so:
var inner = function(x) { console.log(x); }
// test 1
(function(cb) { var x = 123; cb(x); })(inner);
The only way to access the local variable x in the callback, is to pass it as an argument:
var inner = function(some_var) { console.log(some_var); }; //logs 123
(function(cb) { var x = 123; cb(x); })(inner);
OR
var inner = function(some_var) { console.log(some_var); }; //logs 123
(function(cb) { var x = 123; cb.apply(this,[x]); })(inner);
OR
var inner = function(some_var) { console.log(some_var); }; //logs 123
(function(cb) { var x = 123; cb.call(this,x); })(inner);
FURTHER
Because JS is lexically scoped, trying to reference the local variable after the anonymous function has finished executing is impossible by any other means. If you don't pass it as an argument to make it available elsewhere, JS will see it as non-reachable and it will be eligible for garbage collection.
You could redefine the callback function in the current scope:
var inner = function() { console.log(x); }
(function(cb) { var x = 123; eval('cb = ' + cb.toString()); cb(); })(inner);
// or
(function(cb) { var x = 123; eval('(' + cb.toString() + ')')(); })(inner);
This will not work if the function relies on anything in the scope in which it was originally defined or if the Javascript file has been minified. The use of eval may introduce security, performance, and code quality issues.
Have you tried using events? Emit an event inside the anonymous function, then subscribe to it in your own function somewhere else that carries out your logic.
I've been told that javascript variables should all come before they are used in a function, such that:
function contrived() {
var myA, myB;
myA = 10;
myB = 20;
return myA + myB;
}
Is prefered over:
function furtherContrivance() {
var myA = 10;
var myB = 20;
return myA + myB;
}
Is this the case? And why is that?
I guess some people might prefer the former style because that's how it works inside. All local variables exist for the entire lifetime of the function, even if you use var to declare them in the middle of the function.
There's nothing wrong with declaring variables later in the function, syntax-wise, it might just be confusing as the variables will then exist before the line that declares them. Hence this function:
function bar() {
alert(foo); // Alerts "undefined". Not an error because the variable does exist.
var foo = 10;
alert(foo); // Alerts the value 10.
}
Is equivalent to this:
function bar() {
var foo;
alert(foo);
foo = 10;
alert(foo);
}
Another related fact is that nested function definitions (done using function foo() { ... }) will get moved to the top of the containing function as well, so they will be available even if the code that calls them comes before them.
Yes, the variable declaration should come at the top of the function:
function foo() {
var a, b;
}
However, initializing variables can be part of the declaration:
function foo() {
var a = 10, b = 20;
}
The reasoning behind declaring all variables at the top of the function where they are used is to avoid scope confusion.
Here is an example of bad code:
function foo() {
var b;
for (var i = 0; i < 5; i++) {
var a;
a = b = i;
setTimeout(function(){
console.log(a, b);
}, 1000);
}
}
If you execute the code, it will log 4, 4 5 times, rather than counting up. This is because only functions act as closures and introduce new scope. In JavaScript, any var declaration within a function gets executed at the beginning of the function.
This makes the above error much more visible:
function foo() {
var a, b, i;
for (i = 0; i < 5; i++) {
a = b = i;
setTimeout(function(){
console.log(a, b);
}, 1000);
}
}
There is no difference in this case between this two. I'd go with:
function furtherContrivance() {
var myA = 10,
myB = 20;
return myA + myB;
}
which is knows as single var pattern in javascript.
What you really need to take care of is defining your variables in the beginning of your functions. There is a thing in javascript called variables hoisting which means that variable definitions used in function "raise" on top. It's best described by an example:
var x = 'global'; // global (bounded to a global object which is window in browsers)
function func() {
alert(x); // undefined (you expected 'global', right?)
var x = 'local';
alert(x); // local
}
func();
what really happens is called (as I said) variables hoisting (definition of x raises on top), so the code above is actually the same as:
var x = 'global';
function func() {
var x; // definition of `x` raised on top (variables hoisting)
alert(x); // undefined in a local scope
x = 'local';
alert(x);
}
What a javscript interpreter does is it looks inside a function, gathers locally defined variables and raises them on top - this might be a good reason why you should use single var pattern.
In the example you give this is absolutely not the case. In a language like Javascript, it will be more of a developer preference, but it won't have any impact on the result.
Yes, place them at the top. It adds to code clarity.
Try this example:
var x = 1;
(function() {
x++;
alert( x ); // What will this alert show?
var x = 'done';
alert( x );
})();
Looks like it should alert 2, but it alerts NaN.
This is because the variable declaration is hoisted to the top, but the initialization stays in the same place.
So what is actually happening is:
var x = 1;
(function() {
var x;
x++;
alert( x ); // What will this alert show? NaN
x = 'done';
alert( x );
})();
...which makes the NaN expected.
For readability, it's definitely preferred.
However, Javascript "hoists" declarations. Hoisting means that vars and functions will be automatically moved to the top of their scope. This allows you to do things such as use a function before it's declared:
function myScope()
{
test();
function test()
{
//...
}
}
This can lead to some confusion, especially if variables within block scopes are declared. For example:
for(var i in foo)
{
var e = myFunc();
}
The declaration of e will be hoisted to the top of the closure, and e will be initialized to undefined. This allows for some interesting non-intuitive situations, such as:
if(!foo) //Will not throw reference error because foo is declared already
{
var foo = {};
}
So, regardless of how you declare your variables, they'll all get "moved up" to the top of the function anyway.
Hope this helps!
I thought any variable defined in a function would be local but I can easily access variable 'e' outside of its function.
function change() {
var d = 6;
e = 7;
}
change();
alert(e); //> alerts 7
Because new variables will enter the global scope by default. var prevents this from happening by constraining a variable's existence to be within the current scope.
Because it was declared without var it becomes part of the global window object.
You've not explicitly declared it as such, so it has taken global scope.
Thats because e is global by default, using var make a scope varible.
You can read more about this in Javascript Garden Scope and Namespaces
I am guessing that you are going under this assumption that
JSLint expects that a var will be
declared only once, and that it will
be declared before it is used.
Problem with your code is you are using one var, but your second line has no var in front of it. That is pushing that varaible e into the global namespace.
Why is it happening? You used a semicolon instead of a comma in the variable declaration.
function change() {
var d = 6, //Change this to a comma
e = 7;
}
change();
alert(e); //will produce an error now
It is surprisingly easy to create global variables, here are some other gotchas I've seen.
// :-( antipattern: implied global variable
function sum(x, y) {
result = x + y; // result is global
return result;
}
// :-) better
function sum(x, y) {
var result = x + y; // result is local
return result;
}
// :-( antipattern: chain assignments as part of a var declaration
function foo() {
var a = b = 0; // b is global
}
// :-) better
function foo() {
var a, b;
a = b = 0; // both local
}
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?