Function Declaration Vs Function Expression
Solution 1:
The comments in the MDN page are very misleading. (MDN is a collaboratively-edited reference. It's normally excellent. Sometimes it falls a bit short of that.)
From above example,
1) Is function world an expression or declaration?
2) Is function c an expression or declaration?
Until ES2015 (aka "ES6"), they were both unspecified behavior because they were function declarations within a control-flow block. The specification didn't define how they should be handled, but handling them was an "allowable extension" under the spec (blech) and some engines did support them. Unfortunately, different engines supported them by doing different things.
As of ES2015, though, the spec takes them on: They're still function declarations, but how they're interpreted varies depending on whether...
- ...the code is in strict mode (in which the behavior is rational and straightfoward),
- ...the code is in loose mode on a browser-hosted JavaScript engine that implements the optional legacy behavior described by Annex B.3.3 and Annex B.3.4 of the spec (confusing, and there are only a couple of scenarios that are safe cross-browser),
- ...or whether the code is in loose mode on a non-browser JavaScript engine, which in theory isn't supposed to implement Annex B (but that doesn't stop them).
Since in loose mode you can't be sure whether the JavaScript engine is going to implement the Annex B behavior or the non-Annex B behavior, the only reasonable choices are:
- Use strict mode, or
- Don't use block-level function declarations.
If you use strict mode (whether on a browser or not), the behavior is quite straightforward: The declaration is hoisted to the top of its block and is block-scoped (like let
and const
are). The identifier created by the declaration is writable, and so it's as though the declaration were converted to a function expression assigned to a let
variable at the top of the block. Let's take the world
example but add some to it.
This:
"use strict";
// ...functionexample() {
if (x) {
console.log("testing:");
console.log("1:", typeof world);
functionworld() {}
console.log("2:", typeof world);
}
console.log("3":, typeof world);
console.log("4:", world === undefined);
}
...effectively becomes this:
"use strict";
// ...functionexample() {
if (x) {
let world = functionworld() {};
console.log("testing:"); // testing:console.log("1:", typeof world); // 1: functionconsole.log("2:", typeof world); // 2: function
}
console.log("3:", typeof world); // 3: undefinedconsole.log("4:", world === undefined); // ReferenceError: `world` is not defined
}
Notice how the declaraton was hoisted to the top of the block, and is block-scoped.
Outside of strict mode, again, it depends, but the non-legacy version is just like strict mode but with var
instead of let
.
So: this:
This:
// NOT in strict modefunctionexample() {
if (x) {
console.log("testing:");
console.log("1:", typeof world);
functionworld() {}
console.log("2:", typeof world);
}
console.log("3":, typeof world);
console.log("4:", world === undefined);
}
...effectively becomes this:
// NOT in strict modefunctionexample() {
var world;
if (x) {
world = functionworld() {};
console.log("testing:"); // testing: (if executed)console.log("1:", typeof world); // 1: function (if executed)console.log("2:", typeof world); // 2: function (if executed)
}
console.log("3:", typeof world); // 3: function if `x` is truthy, undefined if `x` is falsyconsole.log("4:", world === undefined); // 4: false if `x` is truthy, true if `x` is falsy
}
Post a Comment for "Function Declaration Vs Function Expression"