Difference between function expression in global scope and function declaration - javascript

I'm puzzled by something in my js. Normally I define functions like this:
function f(){
// do stuff
}
but I can also define functions like this:
f = function(){
// do stuff
}
I always thought there is no difference between them, but I now found that this is working:
f = function(){
alert('IT WORKS!!');
}
function createCallback(request){
request.done(function(data){
var html = '';
data['result'].forEach(function(bill){
html += "<tr onclick=\"f();\"><td>" + bill.title + "</td></tr>";
});
$("#someId").html(html);
});
}
but when I define f as follows:
function f(){
alert('IT WORKS!!');
}
and I click on the row, it gives a ReferenceError: f is not defined.
So I wonder: what is actually the difference between function f(){} and f = function(){}?

When you define a function without using var statement, by default the function will be defined as a property in the global scope.
Quoting MDN documentation on var,
Assigning a value to an undeclared variable implicitly creates it as a global variable (it becomes a property of the global object) when the assignment is executed. The differences between declared and undeclared variables are:
Declared variables are constrained in the execution context in which they are declared. Undeclared variables are always global.
Declared variables are created before any code is executed. Undeclared variables do not exist until the code assigning to them is executed.
Declared variables are a non-configurable property of their execution context (function or global). Undeclared variables are configurable (e.g. can be deleted).
Because of these three differences, failure to declare variables will very likely lead to unexpected results. Thus it is recommended to always declare variables, regardless of whether they are in a function or global scope. And in ECMAScript 5 strict mode, assigning to an undeclared variable throws an error.
So, when you define with function function_name(...){...} syntax, it will be in the current scope.
Since the second function definition is in the global scope tr's onclick can find f. Try using var statement like this
var f = function(){
alert('IT WORKS!!');
}
you will get the same ReferenceError: f is not defined.

You forgot the var statement. The function is defined globally when using f = function(){ }. This is why it’s accessible from the onclick handler and the other is not.
Please also read var functionName = function() {} vs function functionName() {} as suggested by #Nehal.

Related

Do I have to use `var` when declaring a function in javascript?

Consider the following 2 functions:
cat = function() {
console.log("Meow");
}
and:
var dog = function() {
console.log("woof")
}
cat() -> "Meow"
dog() -> "Woof
They both work, except that cat is not declared using var. Does this mean that it is globally scoped? I would say that both functions are globally scoped. There is also the syntaxfunction cat(){...}, I guess that is similar to the first style, some sort of implicit variable binding...
Could somebody explain the difference between the styles for declaring functions, if there is any.
Variables
If you don't specify var, let or const it will get globally scoped
If you do specify var, let or const then it will get scoped to the nearest enclosing scope depending on that particular specifier
(var - will get scoped to the nearest enclosing function or global scope if not defined inside of a function)
(let & const - will get scoped to the nearest enclosing block)
Functions
Assigning a function as follows:
var dog = function() {
console.log("woof")
}
Means that the function will not be accessible until the line that it is declared on is reached during execution, i.e. you will only be able to execute this function from after the line on which it was declared.
Whereas declaring a function as follows:
function cat(){...}
Means that it will be moved to the top of the enclosing scope, so you will be able to call it from anywhere within the reachable scope even if it's earlier in code than the line on which you declared it on.
Not using var/let/const makes it implicitly global, which is generally regarded as a bad thing. If you use 'use strict', you'll get an error for any implicit globals. The biggest issue that arises with implicit global variables is that you may not know that you've made a global variable. For example:
(function() {
a = 5;
})();
// a doesn't exist right?
console.log(a); // 5... whoops!
No you don't. you can declare a function like so:
function foo(){
}
Then foo is automatically declared at the appropriate scope.
Its all a matter of scopes. where will the interpreter declare the function. Doing it the way you did it, without var will cause the interpreter to create a global variable automatically, and that is the highest scope possible, meaning that it is accessible everywhere in the code. That is considered a bad thing, since you normally wouldn't want to do that unless it is done intentionally, because of deep reasons which I can go into if you wish.
function foo(){
function bar(){
console.log("bar");
}
bar();
console.log(typeof bar);
}
foo();
bar(); // will throw an error since "bar" does not exist at this scope
Read all about function declaration

when should I put var in front of function in js?

<script type="text/javascript">
var output = function() {console.log('result')}
output();
</script>
If I changed to output = function() {console.log('result')}; it still shows the right result, so my question is:
what is the difference between them? when should I put var in front of function in js? is that the same principle as var in front of variable?
A function defined in a script tag is in the global scope (ie the window object in a browser context) so there is no difference in this case.
Inside a function block, however, is a different story. For example:
foo = function() {
var foo = 1;
console.log(foo);
}
foo(); // logs '1'
foo(); // logs '1'
But:
foo = function() {
foo = 1;
console.log(foo);
}
foo(); // logs '1'
foo(); // SyntaxError: Unexpected token function
Because foo wasn't defined locally, we overwrote the global object.
You're in the global window scope, so there's no difference.
It doesn't matter what the type of the variable is.
If this is declared in functions, then there is a difference:
function name(){
var a=1;
}
alert(a);
Here a will be undefined, as var declares the variable in the scope of the function.
As an excercise:
var a=2;
function name(){
var a=1;
}
name();
alert(a);
This alerts 2 instead of 1, since the middle var belongs in the scope of the function, which is separate from the global scope.
You can also modify global variables this way:
var a=2;
function name(){
a=3;
}
name();
alert(a);
Also compare this with let, which limits it's scope to the block instead: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
"Is that the same principle as var in front of variable?"
Yes. output is a variable.
So I would suggest you use var in front of it when you define it. You could eventually change its value without using var. As in:
var A=1;
A=2;
A=A+1;
Consider the "script" of the funcion as the "value" of that variable.
var F=function() {console.log('one')};
// change it later
F=function() {console.log('two')};
(not suggesting you do this, but to show you it is 100% a var)
You are actually assigning to the variable named "output" a value of "function() {console.log('result')}" not as a string but as a script that gets executed. Note the semicolon at the end like in var A=3;
Now "inside" output there is the code that executes console.log('result'). (more or less, just to explain).
As you usually do not change that same function later (you can, and sometimes it is done) I really suggest you use var in front of it every time you define a function like this, even in cases when it is not strictly necessary, just to be safe you do not override an existing function.
This is a bit different from defining the function as:
function output() {console.log('result')}
Here there is no = sign, no assignment, no semicolon at the end. This is not a variable assignment but a function "definition" although results are similar, and you can call output() in both cases, there are differences. The main one I think is that function definitions are examined before executing the script line by line, while with assignment you really need to have the assignment line processed before you can use the function. So this:
output();
function output() {console.log('result')}
works. While this:
output(); // nope! output not defined yet!
var output=function() {console.log('result')}
doesn't. Variables are assigned or changed when the assignment instruction is read and interpreted.
// here A is undefined, B() prints 'ok'
var A=function() {console.log('first')};
// here A() prints 'first', B() prints 'ok' as usual
A=function() {console.log('second')}; // change it
// here A() prints 'second', B() prints 'ok' as usual
function B() {console.log('ok')}
// same here A() prints 'second', B() prints 'ok'
Without var your variable will be declared as global variable which means it is available on other JS files too. In short If you declare a variable, without using var, the variable always becomes GLOBAL.
Generally there is no difference because you are in the global scope, but in ES5 there's a strict mode, which slightly changes the behavior of undeclared variables. In strict mode, assignment to an undeclared identifier (not putting var in front) is a ReferenceError.
For example:
"use strict";
myVariable = "foo"; // throws a ReferenceError
Function or not function, here's what MDN has to say about var:
The scope of a variable declared with var is the enclosing function or, for variables declared outside a function, the global scope (which is bound to the global object).
Using var outside a function is optional; assigning a value to an undeclared variable implicitly declares it as a global variable (it is now a property of the global object). The difference is that a declared variable is a non-configurable property of the global object while an undeclared is configurable.
And you could also read about the function statement here and the function operator here.
Cheers!

javascript scope of function declarations

The var keyword in javascript causes a variable to be stored in the local scope. Without var variables belong to the global scope. What about functions? It's clear what happens when functions are declared like variables
var foo = function() {...}
but what scope does
function foo() {...}
belong to?
EDIT:
I realized I didn't ask quite the right question so as a follow up. In the outer most nesting is there a difference between the above two declarations and the following declaration?
foo = function() {...}
It belongs to the current scope, always. For example:
// global scope
// foo is a global function
function foo() {
// bar is local to foo
function bar() {
}
}
Regarding your second question, this:
foo = function() {...}
is an anonymous function expression assigned to a global variable (unless you're running is strict mode, then foo would be undefined). The difference between that and function foo() {} is that the latter is a function declaration (versus a variable declaration, which is assigned an anonymous function expression).
You might be interested in this excellent article about function declarations and function expressions: Named function expressions demystified.
Function declarations are always local to the current scope, like a variable declared with the var keyword.
However, the difference is that if they are declared (instead of assigned to a variable) their definition is hoisted, so they will be usable everywhere in the scope even if the declaration comes in the end of the code. See also var functionName = function() {} vs function functionName() {}.
Noteworthy distinction taking implicit globals into account:
var foo = function() {
// Variables
var myVar1 = 42; // Local variable
myVar2 = 69; // Implicit global (no 'var')
// Functional Expressions
var myFn1 = function() { ... } // Local
myFn2 = function() { ... } // Implicit global
function sayHi() {
// I am a function declaration. Always local.
}
}
Hopefully that clarifies a little. Implicit globals are defined if you forget a var before your assignment. Its a dangerous hazard that applies to variable declarations and functional expressions.
Your first example (var foo = function() {...}) is called an anonymous function. It is dynamically declared at runtime, and doesn't follow the same rules as a normal function, but follows the rules of variables.

Variables defined in global scope with identical names

Can anybody explain, why next js code rises two alert windows with 'string1' text rather than to rise the second with 'undefined' text inside?? If both variables are described in the same scope..
var a = 'string1';
alert(a);
var a;
alert(a);​
http://jsfiddle.net/FdRSZ/1/
Thanks
Variable declarations (and function declarations) are hoisted to the top of the scope in which they appear. Assignments happen in place. The code is effectively interpreted like this:
var a;
var a;
a = 'string1';
For example, consider what happens if you declare a variable inside an if statement body:
console.log(myVar); //undefined (NOT a reference error)
if (something === somethingElse) {
var myVar = 10;
}
console.log(myVar); //10
Because JavaScript does not have block scope, all declarations in each scope are hoisted to the top of that scope. If you tried to log some variable that was not declared, you would get a reference error. The above example is interpreted like this:
var myVar; //Declaration is hoisted
console.log(myVar);
if (something === somethingElse) {
myVar = 10; //Assignment still happens here
}
console.log(myVar);
So even if the condition evaluates to false, the myVar variable is still accessible. This is the main reason that JSLint will tell you to move all declarations to the top of the scope in which they appear.
In slightly more detail... this is what the ECMAScript 5 spec has to say (bold emphasis added):
For each VariableDeclaration and VariableDeclarationNoIn d in code, in
source text order do
Let dn be the Identifier in d.
Let
varAlreadyDeclared be the result of calling env’s HasBinding concrete
method passing dn as the argument.
If varAlreadyDeclared is false, then
Call env’s CreateMutableBinding concrete method passing dn and
configurableBindings as the arguments.
Call env’s SetMutableBinding concrete method passing dn, undefined, and strict as the arguments.
So, if a binding already exists with the identifier we are trying to bind now, nothing happens.
Thats because JavaScript does something called variable hoisting. In fact, your JS looks like this:
var a; // hoisted -> declared on top
a = 'string1';
alert(a);
alert(a);
See How Good C# Habits can Encourage Bad JavaScript Habits for more details on how JavaScript works.
That's because the second var a isn't a separate variable declaration. As far as the javascript interpreter is concerned it is the same a as the first one.
var means "Scope this variable to this function" not "Set the value of this variable to undefined".
If the variable is already scoped to the function then var foo means the same as just plain foo

Javascript - Do I need to use 'var' when reassigning a variable defined in the function's parameters?

I've found many definitions of the 'var' statement but most of them are incomplete (usually from introductory guides/tutorials). Should I use 'var' if the variable & scope has been declared in the params list?
someFunc = function(someVar)
{
// Is it considered good practice to use 'var', even if it is redundant?
var someVar = cheese;
};
The answer is no, you shouldn’t be doing this. This is actually considered a bad practice!
JS Lint throws the following error when analyzing your code example:
Problem at line 5 character 16: someVar is already defined.
"I've found many definitions of the 'var' statement but most of them are incomplete."
Try this (a bit stuffy but hopefully complete :-) ): The var keyword declares a new variable, binds it to the current lexical scope, & hoists it to the top of said scope. In other words, the variable will not exist outside of the function that declares it & will be declared before any statements are executed inside the function. Function parameters are implicitly bound to that function's scope so do not require the var keyword.
Nope, the order in which names are defined when entering an execution scope is as follows:
function parameters (with value passed or undefined)
special name arguments (with value of arguments if doesn't exist)
function declarations (with body brought along)
variable declarations (with undefined if doesn't exist)
name of current function (with body brought along, if doesn't exist)
This means that in this code, foo refers to the function parameter (which could easily be changed):
function foo(foo) {
var foo;
alert(foo);
}
foo(1); // 1
If you're using a function declaration inside for foo, that body will override all others. Also, note that this means that you can do this:
function foo(arguments) {
alert(arguments);
}
foo(); // undefined
foo(1); // 1
Don't do that.
No. In Javascript, you can mess with the function argument all you want.
Consider this code, which you see all over the Web and which is used to make code work in standard and IE event models:
function someEventHandler(event) {
event= (event) ? event : window.event;
// statements
}

Categories

Resources