The context:
I am reading the book You Don't Know JS: Up & Going, Chapter 2: Into JavaScript. In the Polyfilling section, the author gives the following example:
if (!Number.isNaN) {
Number.isNaN = function isNaN(x) {
return x !== x;
};
}
So, what is being done here is creating a polyfill so that the ES6 method Number.isNaN can run in older browsers (ie, pre-ES6 versions). As I expected, he makes use of the older isNaN method. The former method is actually meant to deprecate the latter by design.
The question:
Why is isNaN being used as the identifier of the named function expression? I would have expected it to be used in the body somehow. Why? Because all of the identifiers usually seen in examples around the web, when comparing function expressions vs function declarations take the following form:
Function declaration:
function foo() {
// ..
}
Function expression:
var foo = function bar() {
// ..
};
So in this example bar is being defined within the brackets after the 'bar()' string. So why use 'isNaN' above when isNaN is an already defined function within JavaScript? Are we actually overwriting it for the purpose of the polyfill? What am I missing/misunderstanding here?
When you have a named function in an expression, that value is not hoisted but is saved in expression scope. So original value is not changed.
Sample
function bar(){
console.log("In Bar")
}
var foo = function bar(){
console.log("In Foo")
}
bar();
foo();
Why should you use it?
In case of exception, that will help you in debug. An anonymous function will not show any name in stack trace and if you have say 4-5 anonymous functions in 1 function, it becomes difficult as to which one failed. Having a named functions makes it little simple.
var bar = function Test() {
(function() {
(function() {
(function() {
throw new Error("I have no Name2")
})()
})()
})()
}
var foo = function Test() {
(function inFoo1() {
(function inFoo2() {
(function inFoo3() {
throw new Error("I have no Name2")
})()
})()
})();
}
function init() {
try {
foo();
} catch (ex) {
console.log(ex.stack)
}
try {
bar();
} catch (ex) {
console.log(ex.stack)
}
}
function start() {
init();
}
start();
You can also refer to Why using named function expressions? for more information.
Related
So, ES6 has added this way of defining a function,
func() { }
And then we have the old way of doing the same,
function func() {}
As far as, I understand
We can use the new short syntax in object and classes only.
And ES6 classes can only have these short syntax functions, adding long function syntax gives error
I am trying to understand what is the actual implementation difference between the two. Is it related to the use of this or super key word.
Good question!
Here are some of the ways you can declare a function (that can possibly be named doSomething):
Normal function declaration (for the lack of a better world)
This can defined in any block in your code
function doSomething() {
}
Class method and Object shorthand syntax (ES6 only)
These can only be declared inside Class blocks and objects where the function keyword isn't required
class MyClass {
doSomething() { // class method
}
}
// ES6
const myObject = {
foo: 1,
bar: 'baz',
doSomething() { // shorthand: key 'doSomething' whose value is a function
},
}
// ES5 (also ES6)
var myObject = {
foo: 1,
doSomething: function doSomething() {
},
}
Anonymous Functions (functions without a name)
// doesn't have a name but can be invoked using the variable name
const myFunction = function () {}
Callback functions (also can be anonymous)
fetch('/path/to/page').then(function () {
// do something
})
// same as above but with name
fetch('/path/to/page').then(function doSomething() {
// do something
})
Immediately-Invoked Functions (IIFE)
(function doSomething() {
// do something immediately
}())
I'm going to pause here to note that all of the above types of function declaration above have their own scope. Meaning, the this keyword references the actual function, not its surrounding scope.
Arrow functions (lexically scoped)
Meaning that these functions keeps surrounding context when using the this keyword.
const doSomething = () => {
// do something
}
const myObject = {
doSomething: () => {
// do something
}
}
fetch('/path/to/page').then(() => {
// do something
})
(() => {
// do something immediately
})()
Any reason why the following snippet shows different output in Firefox and Chrome:
var sayHo;
console.log(typeof(sayHey));
console.log(typeof(sayHo));
if(true) {
function sayHey() {
console.log("Hey, inside if");
};
sayHo = function() {
console.log("Ho, inside if");
};
}
else {
function sayHey() {
console.log("Hey, inside else");
};
sayHo = function() {
console.log("Ho, inside else");
};
}
sayHey();
sayHo();
Chrome(v31) outputs
function
undefined
Hey, inside else
Ho, inside if
Firefox(v26) outputs
undefined
undefined
Hey, inside if
Ho, inside if
I expected the same output what Chrome gave. During parse time, the function declaration inside will override the function declaration inside if. Because JavaScript will try to hoist both the function declarations, hence the override.
Firefox and Chrome use different JavaScript engines (SpiderMonkey and V8 respectively). The Chrome behaviour can be considered either a 'bug' or an 'ease of use feature'. In V8 function definitions inside if statements (rather than assignment of an anonymous function to a variable) are performed pre-execution. It's a design decision.
It all boils down to hoisting differences :
Function declarations and variable declarations are always moved (“hoisted”) invisibly to the top of their containing scope by the JavaScript interpreter. Function parameters and language-defined names are, obviously, already there. This means that code like this:
function foo() {
bar();
var x = 1;
}
is actually interpreted like this:
function foo() {
var x;
bar();
x = 1;
}
Consider this example :
function test() {
foo(); // TypeError "foo is not a function"
bar(); // "this will run!"
var foo = function () { // function expression assigned to local variable 'foo'
alert("this won't run!");
}
function bar() { // function declaration, given the name 'bar'
alert("this will run!");
}
}
test();
this code is equivalent to :
function test() {
function bar() { // function declaration, given the name 'bar'
alert("this will run!");
}
foo(); // TypeError "foo is not a function"
bar(); // "this will run!"
var foo = function () { // function expression assigned to local variable 'foo'
alert("this won't run!");
}
}
test();
Look what happened to the function declaration : it is hoisted.
Leet's look at simplier sample : http://jsbin.com/UKICENE/4/edit
console.log(typeof(sayHey));
if(true) {
function sayHey() {
console.log("Hey, inside if");
};}
sayHey();
This will yield function in chrome.
But it will yield undefined in FF.
Hoeever - deferring the calculationm via setTimeout will yield the same result as chrome :
console.log(typeof(sayHey));//undefined
setTimeout(function (){console.log(typeof(sayHey));},1000); //function
if(true) {
function sayHey() {
console.log("Hey, inside if");
};}
sayHey();
So , like Šime said , it delay the evaluation.
If you ask me , I think chrome is doing the right thing
JavaScript allows this:
function outside() {
inside();
return 44;
function inside() {
console.log("inside");
}
}
When outside is called the output is:
inside
44
Why does this work and why doesn't it work for other statements like the one below:
function outside() {
return 44;
console.log("inside");
}
which just prints 44.
What you see is the effect of hoisting. When a function is about to be executed, all the variable and function declarations are evaluated first, before the function is really executed. Thus your first function is equivalent to
function outside() {
function inside() {
console.log("inside");
}
inside();
return 44;
}
Details can be found in the specification, 10.4.3 Entering Function Code and 10.5 Declaration Binding Instantiation.
Why does JavaScript allow function declarations after the return statement?
Why the language is defined like this can probably only be answered by Brendan Eich.
Because the file is parsed first and function definitions are read at that time. You are calling the function before you return, so that works just fine. Most programming languages allow you to define functions after calling them, because they all work in two steps: parsing and execution.
In the first case first the function inside is executed and then it comes to return..so it returns 44..
But in the second case the outside function first encounters return which means to exit from that function no matter what is return below... so it only prints 44
function outside() {
inside(); //calling inside();
return 44;
function inside() {
console.log("inside");
}
}
but here
function outside() {
return 44;
console.log("inside");
}
you are just returning not calling inside() at all.
Function declaration:
function myName() {
}
Function Expression:
var myName = function() {
};
These are very different, the function declaration (1) is defined when the Javascript is parsed, and not when it is executed. whereas the function expression (2) is defined when the Javascript is executed.
So technically it is not being defined after the return statement.
At least this is how I understand it.
I use only jQuery for writing JavaScript code. One thing that confuses me is these two approaches of writing functions,
First approach
vote = function (action,feedbackId,responseDiv)
{
alert('hi');
return feedbackId;
}
Second approach
function vote(action, feedbackId,responseDiv)
{
alert('hi');
return feedbackId;
}
What is the difference between the two and why should one use the first approach or the second approach?
The first is a function expression assigned to the vote variable, the second is a function declaration.
The main difference is that function statements are evaluated at parse time, they are available before its declaration at runtime.
See also:
Named function expressions demystified (article)
Explain JavaScript’s encapsulated anonymous function syntax
function myFunction() {}
...is called a "function declaration".
var myFunction = function() {};
...is called a "function expression".
They're very similar; however:
The function declaration can be declared after it is referenced, whereas the function expression must be declared before it is referenced:
// OK
myFunction();
function myFunction() {}
// Error
myFunction();
var myFunction = function() {};
Since a function expression is a statement, it should be followed by a semi-colon.
See Function constructor vs. function declaration vs. function expression at the Mozilla Developer Centre for more information.
The function declaration syntax cannot be used within a block statement.
Legal:
function a() {
function b() {
}
}
Illegal:
function a() {
if (c) {
function b() {
}
}
}
You can do this though:
function a() {
var b;
if (c) {
b = function() {
};
}
}
The first one is a function expression,
var calculateSum = function(a, b) { return a + b; }
alert(calculateSum(5, 5)); // Alerts 10
The second one is a plain function declaration.
I'm trying to understand when to use anonymous JavaScript functions.
State differences between the functions? Explain when you would use each.
var test1 = function(){
$("<div />").html("test1").appendTo(body)
};
function test2() {
$("<div />").html("test2").appendTo(body)
}
I think the answer is that one uses anonymous function and the other doesn't to replace an empty div element. Does that seem right?
In your example it really doesn't make a huge difference. The only difference is that functions declared using function foo() { } are accessible anywhere within the same scope at any time, while functions declared using var foo = function () { } are only accessible after the code that does the assignment has run.
foo(); // ok
function foo() { ... };
bar(); // error, bar is not a function
var bar = function () { ... };
bar(); // ok
You usually use anonymous functions in cases where you don't need a named function, or where you're constructing objects:
arr.sort(function (a, b) { return a - b; }); // anonymous callback function
function MyObject() {
this.foo = function () { ... } // object constructor
}
You would use a function like the following (which is another type of anonymous function) when you do not want to pollute the global namespace:
(function() {
var pollution = 'blablabla';
function stinky() {
// Some code
}
})();
You may check John Resig's Secrets of JavaScript Libraries, especially page 47 for JavaScript function. Quite lengthy, but you'll learn more about JavaScript