Function statement vs function expression weird behaviour - javascript

var a = function b() {
};
console.log(typeof b); //gives undefined
console.log(typeof a); //gives function
Why the difference in the two outputs?
I understand the difference between function expression and function statement, but not able to understand the output above.
From what I know, javascript makes var a point to the memory allocated to named function b here. In such a case typeof b should also return function but it returns undefined
Any explanations?

Because the name of a named function expression is scoped to the expression.
var a = function b() {
console.log(typeof b); //gives function
console.log(typeof a); //gives function
};
console.log(typeof b); //gives undefined
console.log(typeof a); //gives function
a();

Why the difference in the two outputs?
You're taking a function expression for a function named b and assigning it to a variable named a. That means a is in scope where the expression occurs, but b is not; it's only in scope within the function. (The whole function, including the parameter list; that last part is only relevant for ES2015+, not ES5 and earlier: You can use b as the value of a default parameter.)
You probably expected b to be in scope where the expression was, because that's true for a function declaration:
function b() {
}
console.log(typeof b);
But this is just a difference in how function declarations and function expressions are handled.

With
function b(){
}
you declare a function called b. This statement has no return value and therefor the return value is undefined.
To declare an anonymous function you have to omit the function name in the declaration, like this:
function(){
};
This one is just a function literal you can assign to a variable like that:
var a = function(){
};

Related

TDZ in undeclared variables of function parameters [duplicate]

This question already has an answer here:
Scope of Default function parameters in javascript
(1 answer)
Closed 4 years ago.
When I try to run the foo function defined in this snippet I get a ReferenceError since b is not defined.
var b = 3;
function foo( a = 42, b = a + b + 5 ) {
// ..
}
foo()
This looks like a TDZ error because b has been defined in the outer scope but it's not yet usable in the function signature as a right-hand-side value.
This is what I think the compiler should do:
var b;
function foo(..) { .. }
// hoist all functions and variables declarations to the top
// then perform assignments operations
b = 3;
foo();
//create a new execution environment for `foo`
// add `foo` on top of the callstack
// look for variable a, can't find one, hence automatically create a
`var a` in the local execution environment and assign to it the
value `42`
// look for a `var b` in the global execution context, find one, use
the value in it (`3`) as a right-hand-side value.
This shouldn't raise a ReferenceError. Looks like this is not what happens here.
Can someone explain in what actually does the compiler do and how it processes this code?
On every function call, the engine evaluates some prologue code, which contains formal parameters, declared as let vars and initialized with their actual values or default expressions, if provided:
var b = 3;
function foo( ) {
let a = <actual param for a> OR 42;
let b = <actual param for b> OR a + b + 5;
// ..
}
Since b in a function is lexical (let), it's not possible to access its value before initialization. Hence the ReferenceError.
Note that this is a call-time error, so the following compiles fine:
var b = 1
function foo(b=b) {
console.log(b)
}
The error happens when you actually call the function:
var b = 1
function foo(b=b) {
console.log(b)
}
foo()
and only when the engine actually evaluates the faulty default expression:
var b = 1
function foo(b=b) {
console.log(b)
}
foo(7)
ECMA standard reference: FunctionDeclarationInstantiation, p.21:
For each String paramName in parameterNames, do
...Perform ! envRec.CreateMutableBinding(paramName, false).
The function arguments somewhat works like 'let'.
We cannot access variable created using 'let' before they are declared .i.e variables created using 'let' are not hoisted.
This happens because if the we are declaring the variable in local scope , it cannot access the global scope variable(Unless 'this' is used )
Your code can be fixed by this -
var b = 3;
function foo( a = 42, b = a + this.b + 5 ) {
// default binding. In this case this.b = global var
}
foo()
you can also see this error if you do this.
let variable = variable;

Different JavaScript function format

I've been wondering what is the difference between:
function getBasicRow() {}
getBasicRow : function() {}
I've seen the 2nd function used by vtiger CRM and hifive (http://www.htmlhifive.com/)
The second one assigns the function to a property on some object literal, so the scope of the function is determined by the property.
The first one creates a named function without assigning it to a variable. The function will be hoisted to the closest function scope.
An elobrative explanation that I found here and would like to share it.
The different ways in which a function can be defined in javascript are:
function A(){}; // function declaration
var B = function(){}; // function expression
var C = (function(){}); // function expression with grouping operators
var D = function foo(){}; // named function expression
var E = (function(){ // immediately-invoked function expression (IIFE) that returns a function
return function(){}
})();
var F = new Function(); // Function constructor
var G = new function(){}; // special case: object constructor
What exactly is hoisting?
The interesting thing about these is that they are “hoisted” to the top of their scope, which means this code:
A();
function A(){
console.log('foo');
};
Gets executed as this code:
function A(){
console.log('foo');
};
A();
Which practically means that, yes, you can call the functions before they’re written in your code. It won’t matter, because the entire function gets hoisted to the top of its containing scope.
Variable declaration hoisting
Variable declarations are hoisted to the top of their scope, somewhat similarly to function hoisting except the contents of the variable are not hoisted as well. This happens with all variables, and it means it’s now happening with our functions, now that we’re assigning them to variables.
This code:
var A = function(){};
var B = function(){};
var C = function(){};
Will be executed as this:
var A, B, C; // variable declarations are hoisted
A = function(){};
B = function(){};
C = function(){};
Therefore the order of setting and calling this type of function is important:
// this works
var B = function(){};
B();
// this doesn't work
B2(); // TypeError (B2 is undefined)
var B2 = function(){};
The second example gives us an error because only the variable B2’s declaration is hoisted, but not its definition, thus the “undefined” error.
Courtesy: DavidBCalhoun

Lexical scope/closures in javaScript

I understand functions in 'js' have lexical scope (i.e. functions create their environment (scope) when they are defined not when they are executed.)
function f1() {
var a = 1;
f2();
}
function f2() {
return a;
}
f1(); // a is not defined
When I run just 'f()' it returns the inner function. Which I get, that's what 'return' does!
function f() {
var b = "barb";
return function() {
return b;
}
}
console.log(b); //ReferenceError: b is not defined
Why do you get 'ReferenceError: b is not defined?'
But doesn't the inner function above have access to it's space, f()'s space etc. Being that 'b' is being returned to the global space, wouldn't the console.log() work?
However when I assign 'f()' to a new variable and run it:
var x = f();
x();// "barb"
console.log(b); //ReferenceError: b is not defined
This returns 'b' which is "barb", but when you run console.log() again you'll get 'ReferenceError: 'b' is not defined'; Isn't 'b' in the global scope now since it has been returned? SO why didn't 'x()' also return the inner function just like 'f()' did?
You, my friend, are thoroughly confused. Your very first statement itself is wrong:
functions create their environment (scope) when they are defined not when they are executed
Actually it's the opposite. Defining a function doesn't create a scope. Calling a function creates a scope.
What's a scope?
To put it simply, a scope is the lifespan of a variable. You see, every variable is born, lives and dies. The beginning of a scope marks the time the variable is born and the end of the scope marks the time it dies.
In the beginning there's only one scope (called the program scope or the global scope). Variables created in this scope only die when the program ends. They are called global variables.
For example, consider this program:
const x = 10; // global variable x
{ // beginning of a scope
const x = 20; // local variable x
console.log(x); // 20
} // end of the scope
console.log(x); // 10
Here we created a global variable called x. Then we created a block scope. Inside this block scope we created a local variable x. Since local variables shadow global variables when we log x we get 20. Back in the global scope when we log x we get 10 (the local x is now dead).
Block Scopes and Function Scopes
Now there are two main types of scopes in programming - block scopes and function scopes.
The scope in the previous example was a block scope. It's just a block of code. Hence the name. Block scopes are immediately executed.
Function scopes on the other hand are templates of block scopes. As the name suggests a function scope belongs to a function. However, more precisely, it belongs to a function call. Function scopes do not exist until a function is called. For instance:
const x = 10;
function inc(x) {
console.log(x + 1);
}
inc(3); // 4
console.log(x); // 10
inc(7); // 8
As you can see every time you call a function a new scope is created. That's the reason you get the outputs 4, 10 and 8.
Originally, JavaScript only had function scopes. It didn't have block scopes. Hence if you wanted to create a block scope then you had to create a function and immediately execute it:
const x = 10; // global variable x
(function () { // beginning of a scope
const x = 20; // local variable x
console.log(x); // 20
}()); // end of the scope
console.log(x); // 10
This pattern is called an immediately invoked function expression (IIFE). Of course, nowadays we can create block scoped variables using const and let.
Lexical Scopes and Dynamic Scopes
Function scopes can again be of two types - lexical and dynamic. You see, in a function there are two types of variables:
Free variables
Bound variables
Variables declared inside a scope are bound to that scope. Variables not declared inside a scope are free. These free variables belong to some other scope, but which one?
Lexical Scope
In lexical scoping free variables must belong to a parent scope. For example:
function add(x) { // template of a new scope, x is bound in this scope
return function (y) { // template of a new scope, x is free, y is bound
return x + y; // x resolves to the parent scope
};
}
const add10 = add(10); // create a new scope for x and return a function
console.log(add10(20)); // create a new scope for y and return x + y
JavaScript, like most programming languages, has lexical scoping.
Dynamic Scope
In contrast to lexical scoping, in dynamic scoping free variables must belong to the calling scope (the scope of the calling function). For example (this is also not JS - it doesn't have dynamic scopes):
function add(y) { // template of a new scope, y is bound, x is free
return x + y; // x resolves to the calling scope
}
function add10(y) { // template of a new scope, bind y
var x = 10; // bind x
return add(y); // add x and y
}
print(add10(20)); // calling add10 creates a new scope (the calling scope)
// the x in add resolves to 10 because the x in add10 is 10
That's it. Simple right?
The Problem
The problem with your first program is that JavaScript doesn't have dynamic scoping. It only has lexical scoping. See the mistake?
function f1() {
var a = 1;
f2();
}
function f2() {
return a;
}
f1(); // a is not defined (obviously - f2 can't access the `a` inside f1)
Your second program is a very big mess:
function f() {
var b = "barb";
return function() {
return b;
}
}
console.log(b); //ReferenceError: b is not defined
Here are the mistakes:
You never called f. Hence the variable b is never created.
Even if you called f the variable b would be local to f.
This is what you need to do:
function f() {
const b = "barb";
return function() {
return b;
}
}
const x = f();
console.log(x());
When you call x it returns b. However that doesn't make b global. To make b global you need to do this:
function f() {
const b = "barb";
return function() {
return b;
}
}
const x = f();
const b = x();
console.log(b);
Hope this helped you understand about scopes and functions.
You get, "ReferenceError: b is not defined" because "b" is not defined where your console.log() call is. There's a "b" inside that function, but not outside. Your assertion that "b is being returned to the global space" is false.
When you invoke the function returned by your "f()" function, that will return a copy of the value referenced by that closure variable "b". In this case, "b" will always be that string, so the function returns that string. It does not result in the symbol "b" becoming a global variable.
But doesn't the inner function above have access to it's space, f()'s space etc.
Yes it has. It accesses the b variable and returns its value from the function.
Being that 'b' is being returned to the global space
No. Returning a value from a function is not "making a variable available in the caller scope". Calling the function (with f()) is an expression whose result is the value that the function returned (in your case, the unnamed function object). That value can then be assigned somewhere (to x), a property of it can be accessed or it can be discarded.
The variable b however stays private in the scope where it was declared. It is not [getting] defined in the scope where you call console.log, that's why you get an error.
What you want seems to be
var x = f();
var b = x(); // declare new variable b here, assign the returned value
console.log( b ); // logs "barb"
function f1() {
var a = 1;
f2();
}
function f2() {
return a;
}
f1(); // a is not defined
f2(); does not knows about the a,because you never passed 'a' to it,(That's Scope are
created when the functions are defined).Look function f2() would have been able to acess
a if it was defined inside f1();[Functions can access the variables in same scope in
which they are "DEFINED" and NOT "CALLED"]
function f() {
var b = "barb";
return function(){
return b;
}
}
console.log(b);
First of all You Need to Call f(); after executing f(); it would return another function
which needs to be executed. i.e
var a=f();
a();
it would result into "barb" ,In this case you are returning a function not the var b;
function f() {
var b = "barb";
return b;
};
console.log(f());
This would print barb on screen

Functions that return a function

I'm stuck with this concept of 'Functions that return functions'. I'm referring the book 'Object Oriented Javascript' by Stoyan Stefanov.
Snippet One:
function a() {
alert("A!");
function b() {
alert("B!");
}
return b();
}
var s = a();
alert("break");
s();
Output:
A!
B!
break
Snippet Two
function a() {
alert('A!');
function b(){
alert('B!');
}
return b;
}
var s = a();
alert('break');
s();
Output:
A!
break
B!
Can someone please tell me the difference between returning b and b() in the above snippets?
Assigning a variable to a function (without the parenthesis) copies the reference to the function. Putting the parenthesis at the end of a function name, calls the function, returning the functions return value.
Demo
function a() {
alert('A');
}
//alerts 'A', returns undefined
function b() {
alert('B');
return a;
}
//alerts 'B', returns function a
function c() {
alert('C');
return a();
}
//alerts 'C', alerts 'A', returns undefined
alert("Function 'a' returns " + a());
alert("Function 'b' returns " + b());
alert("Function 'c' returns " + c());
In your example, you are also defining functions within a function. Such as:
function d() {
function e() {
alert('E');
}
return e;
}
d()();
//alerts 'E'
The function is still callable. It still exists. This is used in JavaScript all the time. Functions can be passed around just like other values. Consider the following:
function counter() {
var count = 0;
return function() {
alert(count++);
}
}
var count = counter();
count();
count();
count();
The function count can keep the variables that were defined outside of it. This is called a closure. It's also used a lot in JavaScript.
Returning the function name without () returns a reference to the function, which can be assigned as you've done with var s = a(). s now contains a reference to the function b(), and calling s() is functionally equivalent to calling b().
// Return a reference to the function b().
// In your example, the reference is assigned to var s
return b;
Calling the function with () in a return statement executes the function, and returns whatever value was returned by the function. It is similar to calling var x = b();, but instead of assigning the return value of b() you are returning it from the calling function a(). If the function b() itself does not return a value, the call returns undefined after whatever other work is done by b().
// Execute function b() and return its value
return b();
// If b() has no return value, this is equivalent to calling b(), followed by
// return undefined;
return b(); calls the function b(), and returns its result.
return b; returns a reference to the function b, which you can store in a variable to call later.
Returning b is returning a function object. In Javascript, functions are just objects, like any other object. If you find that not helpful, just replace the word "object" with "thing". You can return any object from a function. You can return a true/false value. An integer (1,2,3,4...). You can return a string. You can return a complex object with multiple properties. And you can return a function. a function is just a thing.
In your case, returning b returns the thing, the thing is a callable function. Returning b() returns the value returned by the callable function.
Consider this code:
function b() {
return 42;
}
Using the above definition, return b(); returns the value 42. On the other hand return b; returns a function, that itself returns the value of 42. They are two different things.
When you return b, it is just a reference to function b, but not being executed at this time.
When you return b(), you're executing the function and returning its result.
Try alerting typeof(s) in your examples. Snippet b will give you 'function'. What will snippet a give you?
Imagine the function as a type, like an int. You can return ints in a function.
You can return functions too, they are object of type "function".
Now the syntax problem: because functions returns values, how can you return a function and not it's returning value?
by omitting brackets! Because without brackets, the function won't be executed! So:
return b;
Will return the "function" (imagine it like if you are returning a number), while:
return b();
First executes the function then return the value obtained by executing it, it's a big difference!
Snippet one:
function a() {
alert('A!');
function b(){
alert('B!');
}
return b(); //return nothing here as b not defined a return value
}
var s = a(); //s got nothing assigned as b() and thus a() return nothing.
alert('break');
s(); // s equals nothing so nothing will be executed, JavaScript interpreter will complain
the statement 'b()' means to execute the function named 'b' which shows a dialog box with text 'B!'
the statement 'return b();' means to execute a function named 'b' and then return what function 'b' return. but 'b' returns nothing, then this statement 'return b()' returns nothing either.
If b() return a number, then ‘return b()’ is a number too.
Now ‘s’ is assigned the value of what 'a()' return, which returns 'b()', which is nothing, so 's' is nothing (in JavaScript it’s a thing actually, it's an 'undefined'. So when you ask JavaScript to interpret what data type the 's' is, JavaScript interpreter will tell you 's' is an undefined.) As 's' is an undefined, when you ask JavaScript to execute this statement 's()', you're asking JavaScript to execute a function named as 's', but 's' here is an 'undefined', not a function, so JavaScript will complain, "hey, s is not a function, I don't know how to do with this s", then a "Uncaught TypeError: s is not a function" error message will be shown by JavaScript (tested in Firefox and Chrome)
Snippet Two
function a() {
alert('A!');
function b(){
alert('B!');
}
return b; //return pointer to function b here
}
var s = a(); //s get the value of pointer to b
alert('break');
s(); // b() function is executed
now, function 'a' returning a pointer/alias to a function named 'b'. so when execute 's=a()', 's' will get a value pointing to b, i.e. 's' is an alias of 'b' now, calling 's' equals calling 'b'. i.e. 's' is a function now. Execute 's()' means to run function 'b' (same as executing 'b()'), a dialog box showing 'B!' will appeared (i.e. running the 'alert('B!'); statement in the function 'b')
Create a variable:
var thing1 = undefined;
Declare a Function:
function something1 () {
return "Hi there, I'm number 1!";
}
Alert the value of thing1 (our first variable):
alert(thing1); // Outputs: "undefined".
Now, if we wanted thing1 to be a reference to the function something1, meaning it would be the same thing as our created function, we would do:
thing1 = something1;
However, if we wanted the return value of the function then we must assign it the return value of the executed function. You execute the function by using parenthesis:
thing1 = something1(); // Value of thing1: "Hi there, I'm number 1!"
Here is a nice example to show how its work in practice:
when you call in with two parameter and returns a result
function sum(x, y) {
if (y !== undefined) {
return x + y;
} else {
return function(y) { return x + y; };
}
}
console.log(sum(3)(8))
there is also another way using the accessing to the arguments in js:
function sum(x) {
if (arguments.length == 2) {
return arguments[0] + arguments[1];
} else {
return function(y) { return x + y; };
}
}
Let's try to understand the "return" concept with two examples with the same output, one without using the "return" concept and the other with the "return" concept, both giving the same outcome.
let myLuckyNumber = 22
function addsToMyLuckyNumber(incrementBy, multiplyBy) {
myLuckyNumber = (myLuckyNumber + incrementBy) * multiplyBy
}
addsToMyLuckyNumber(5, 2)
console.log(myLuckyNumber)
const myLuckyNumber = 22
function addsToMyLuckyNumber(incrementBy, multiplyBy) {
return (myLuckyNumber + incrementBy) * multiplyBy
}
myNewLuckyNumber = addsToMyLuckyNumber(5,2)
console.log(myLuckyNumber, myNewLuckyNumber)
In the first snippet, you can see the code
myLuckyNumber = (myLuckyNumber + incrementBy) * multiplyBy
you cannot assign a similar code to the second snippet, since it will not work, so we use "return" concept and assign a new variable.
function addsToMyLuckyNumber(incrementBy, multiplyBy) {
return (myLuckyNumber + incrementBy) * multiplyBy
}
myNewLuckyNumber = addsToMyLuckyNumber(5,2)

Calling function with window scope explanation (0, function(){})()

I am curious as to why this works:
var c = {
d: function myFunc() {
console.log(this === window);
}
};
var a = {
b: function() {
console.log(this === a);
(0,c.d)();
c.d();
}
};
a.b();
Console output:
True
True
False
So it seems to be that (0, c.d)() is the same as c.d.call(window), but I cannot seem to find much about why or how this works. Can anyone explain?
From: Closure Compiler Issues
Fiddle: http://jsfiddle.net/wPWb4/2/
If you write multiple expressions separated by a comma (,), then all expressions will be evaluated, but you will end up with the value of the last expression:
var x = (1,2,3);
console.log(x); // this will log "3"
Now (0,c.d) is an expression that will return the function c.d, but now c is not the this of the function anymore. This means that this will point to the global object (window), or remain undefined in strict mode. You would get the same effect with any of these:
var f = function(x) { return x; };
f(c.d)();
Or just
var f = c.d;
f();
The expression (0, myFunc) is equivalent to just myFunc. The comma operator takes multiple expressions, evaluate them, and returns the last expression, so (0, myFunc) returns just myFunc.
Now, in your b method, this is equal to a because b is attached to a. In other words, b can be called by a.b(). However, myFunc is not attached to a (you can't call myFunc by a.myFunc()), so in myFunc, this can't be a. In fact, myFunc is called without setting its this so it defaults to the global object window (or remains undefined in strict mode), and therefore its this is equal to window.
You might be wondering what the point of the (0, listeners[i])() is, then, when they could have just written listeners[i](). Consider this code that creates an array with two elements, both functions:
var listeners = [
function () { alert(this); },
function () { alert(this); }
];
When you call listeners[0](), then in the listeners[0] function, this is equal to listeners, because 0 is attached to listeners, just like how b was attached to a. However, when you call the function by (0, listeners[0])(), listeners[0] is "decoupled" from the listeners array.* Since the decoupled function no longer is attached to anything, its this is the global object window.
*It's as if you wrote:
var temp = listeners[0];
temp();

Categories