Modern JavaScript Tutorial Part 1.6 Advanced Study of Functions - Second
- javascript
This is the second article summarizing Modern JavaScript Part 1.6.
1. The Old var
In addition to let
and const
, variables can also be declared using var
. This was the original method used in JavaScript.
In many cases, changing let
to var
operates similarly. However, there are some significant differences.
1.1. Scope
Unlike let
, which divides scope based on blocks, var
only has function scope and global scope. Therefore, blocks that are not function scope do not separate scope.
if (1) {
var a = 1;
console.log(a);
}
console.log(a);
// Since the if block does not have function scope,
// var does not separate scope, so a is accessible here
Conversely, scope is divided based on functions.
function foo() {
var bar = 1;
}
foo();
console.log(bar);
// Referencing bar outside the function will cause a ReferenceError
1.2. Variable Redeclaration
var
allows for redeclaration within the same scope. However, if a variable has already been declared, redeclaring it with var
assigns a value to the variable without allocating new memory.
var a = 1; // At this point, a has already been declared
var a = 2;
var a = 3;
console.log(a); // Outputs 3
1.3. Usage Before Declaration
The declaration of var
occurs at the beginning of the function, regardless of where it is declared within the function. Therefore, it can be used anywhere in the function body, even before encountering var
. However, only the declaration is processed, and the assignment of values is not handled until the beginning of the script.
function foo() {
// The declaration of a has been processed, but its value is not assigned, so undefined is output.
console.log(a);
var a = 1;
}
foo();
If a value is assigned beforehand, that value will be processed.
function foo() {
a = 2;
console.log(a); // 2
var a = 1;
console.log(a); // 1
}
foo();
Of course, it cannot be used outside the function.
function foo() {
var a = 1;
console.log(a);
}
console.log(a); // Error
foo();
1.4. IIFE
IIFE stands for Immediately Invoked Function Expression, which refers to declaring a function and executing it immediately. This allows for using var
as a block-level scope alternative.
An immediately invoked function expression is created by wrapping a function expression in parentheses.
(function () {
let msg = "Hello World";
console.log(msg);
})();
// hello world
This can be used to mimic private members. This was a trick used when only var
was available.
var User = (function () {
var name = "김성현";
return function () {
this.getName = function () {
return name;
}
this.setName = function (newName) {
name = newName;
}
}
})();
var user1 = new User();
console.log(user1.name); // undefined
console.log(user1.getName()); // 김성현
user1.name = "다른 이름";
console.log(user1.getName()); // 김성현
user1.setName("다른 이름");
console.log(user1.getName()); // 다른 이름
In the above example, the User function is called immediately. After the call ends, the local variable name within the function (originally) disappears. Additionally, it cannot be accessed in the general way.
However, the hidden property [[Environment]]
of the function returned by the immediately invoked function retains its lexical environment, so functions (here, getName and setName) can access the lexical environment of the immediately invoked function and thus access name. This is how we can mimic private access.
2. The Global Object
The global object is typically built into the language or host environment. In the browser environment, it's called window
, and in Node.js, it's global
, but recently it has been standardized to globalThis
.
Variables declared with var
(as opposed to let
or const
) are properties of the global object. However, it is generally advisable not to use var
, and similarly to avoid using such methods to access the global object. Using let
prevents access to variables through the global object.
If you want to create a variable that can be used everywhere, you can directly add it to the global object.
globalThis.authorName = "김성현";
console.log(authorName);
A variable added in this way to the global object can be accessed anywhere in the script. However, creating global variables is not recommended.
3. Named Function Expressions
A named function expression is literally a function expression that has a name.
Consider the following code. There is a name attached to the function expression.
let foo = function bar() {
console.log("SH");
}
This does not prevent foo
from being called, and it operates the same as a regular function expression. So what's different?
It can reference itself within the function expression, but the name cannot be used outside the expression.
let greeting = function func(name) {
if (name) {
console.log(`안녕하세요 ${name}님`);
}
else {
func("김성현");
}
}
greeting(); // 안녕하세요 김성현님
func(); // An error occurs because func is not accessible outside the named function expression
However, this could easily be done by substituting greeting
instead of func
. Thus, it is not necessary to name the function expression. What is the benefit of this? It occurs when greeting
is assigned to another function.
let greeting = function (name) {
if (name) {
console.log(`안녕하세요 ${name}님`);
}
else {
greeting("김성현");
}
}
greeting(); // 안녕하세요 김성현님
let foo = greeting;
greeting = null;
foo();
// An error occurs because foo cannot access greeting's outer lexical environment
On the other hand, using a named function expression keeps the name of the function within the local lexical environment of the function, allowing the usage of that name regardless of what the outer function's name was.
let greeting = function func(name) {
if (name) {
console.log(`안녕하세요 ${name}님`);
}
else {
func("김성현");
}
}
greeting(); // 안녕하세요 김성현님
let foo = greeting;
greeting = null;
foo();
// 안녕하세요 김성현님
You can always use the internal name of the function expression to call itself. JavaScript guarantees that the name given to a function expression will always refer to that particular function.
3.1. Function Properties
Since functions are objects, properties can be attached to them and they also have default properties such as name
and length
.
References
https://coderwall.com/p/ta4caw/using-iife-to-create-private-members-in-javascript