JavaScript Basic - Function, Function Expression, Block Scope, Callback function, Arrow Function...
Tags: javascript, function, callback, blockscope
Published: 2021-12-03 00:10:18


#Function
## Why do we use function?
- it's reusable
- to understand the architecture
- easy to manage, maintain the code and etc

Quite often we need to perform a similar action in many places of the script. For example, we need to show a nice-looking message when a user logs in, logs out and maybe somewhere else.
Functions are one of the fundamental **building blocks** in JavaScript and program.
They **_allow the code to be called many times without repetition_**.

#Function declaration
The <u>**_function keyword_**</u> goes first, then goes the <u>**_name of the function_**</u>, then <u>**_a list of parameters between the parentheses_**</u> and finally the <u>**_code of the function_**</u>, also named “the function **body**”, **between curly braces**.
```js
function functionName(parameters) {
  //function body - code here
}
```
To create a function we can use a function declaration. The function below can be called by its name: greetingMessage()
```js
function greetingMessage() {
  console.log("Hello, Nice to meet you!");
}

greetingMessage()
// "Hello, Nice to meet you!"
```

#Scope
Scope defines <u>**where variables can be accessed or referenced**</u>. While some variables can be accessed from anywhere within a program, other variables may only be available in a specific context.
```js
function one() {
  let x = 10;
  console.log("called function one");
}

function two() {
  let y = 10;
  console.log("called function two");
}

one();
// "called function one"

two();
// "called function two"

// block scope, function scope

y;
// Uncaught ReferenceError: y is not defined
// you cannot access to the variable declared inside function.
```
**NOTE!** You CANNOT access to variables declared inside function. _**function creates a scope**_, so that (for example) a <u>variable defined exclusively within the function cannot be accessed from outside the function or within other functions</u>. 
(I'll write about block scope more in detail at the end)

# Local variable
A **_variable declared inside a function_** is <u>only visible inside that function</u>.
```js
function greetingMessage() {
  let message = "Hello, Nice to meet you!"; // local variable
  console.log(message);
}
greetingMessage(); // "Hello, Nice to meet you!"

console.log(message); // ReferenceError: message is not defined 
// Because message is a local variable inside of function. It causes error!!
```

# Global variable
```js
let userName = "Hailey";

function greetingMessage(); {
  let message = "Hello, " + userName;
  console.log(message);
}
greetingMessage();; // Hello, Hailey
```
The function has full access to the outer variable. It can modify it as well. For instance,
```js
let userName = "Hailey";

function greetingMessage(); {
  userName = "Lilly"; // (1) changed the outer variable

  let message = "Hello, " + userName;
  console.log(message);
}

console.log(userName); // "Hailey" - before the function call

greetingMessage();

console.log(userName); // "Lilly" - the value was modified by the function. now userName = "Lilly".
```
The outer variable is **only used if there’s no local one.**
_**If a same-named variable is declared inside the function**_ then <u>**it shadows the outer one**</u>. For instance, in the code below the function uses the local userName. **<u>The outer one is ignored**</u>
```js
let userName = "Hailey";
function greetingMessage() {
  let userName = "Lilly"; // declare a local variable with the same name from outside one.

  let message = "Hello, " + userName; // Lilly
  console.log(message);
}

// the function will create and use its own userName and will use this only.
greetingMessage();

console.log(userName); // "Lilly" - unchanged, the function did not access the outer variable.
```
Variables declared outside of any function, such as the outer userName in the code above, are called <u>**global variable**</u>.
Global variables are visible from any function (unless shadowed by locals).
It’s a good practice to **_minimize the use of global variables_**. Modern code has few or no globals. Most variables reside in their functions. Sometimes though, they can be useful to store project-level data.
```js
let k = 10;
function viewK() {
  console.log(k);
}
function changeK() {
  k += 10;
  console.log(k);
}
viewK();
changeK();
viewK();
// 10
// 20
// 20 - because changeK() changed value of global variable k.
// You can change value of global variable from inside of function like this.

let k = 10;
function viewK() {
  console.log(k);
}
function changeK() {
  let k = 20;
  console.log(k);
}
viewK();
changeK();
viewK();
// 10
// 20
// 10
// If you declare local variable inside function and if that local variable has the same name with global variable, the global variable get shadowed and you cannot access to it. 
```

# Parameter, Argument
We can pass arbitrary(*임의의) data to functions using parameters.

```js
function add(a, b) {
  return a + b;
}
add(10, 20);
//30
```
**Parameter**: A parameter is the _**variable listed inside the parentheses in the function declaration**_ (it’s a declaration time term) 
**Argument**: An argument is the **_value that is passed to the function_** when it is called (it’s a call time term)

From function above -  add(a, b), the variable listed inside parentheses a, b are parameters.
What's passed to the function add(10, 20) - 10, 20 are the arguments.

#Default value(Default parameters)
In JavaScript, parameters of functions default to **undefined**. If a function is called, then the corresponding value becomes undefined. However, in some situations it might be useful to **_set a different default value_**. This is exactly what default parameters do.
## How to set default value of function?
```js
function add(a = 100, b = 200) {
  return a + b;
}
add(); //300
// if argument is empty, it gets all of the values from default value.
// Because function add has default values now, even if it doesn't receive any arguments, it gets (a = 100, b = 200) as value instead of becoming undefined.

add(10, 20);
//30
add(10); // if you pass only one argument but there are more of parameters, it takes the argument as the first parameter so, a = 10
//210
```
## Another way to set default value
```js
function add(a = 100, b = 200) {
  return a + b;
}
add((b = 300)); // 500 not 400
// If you pass only one argument, it takes it as first parameter no matter what (even if you specify the property name of value like b = 300)

add(undefined, 300); // Even if you'd like to pass value only for 'b', you still have to pass value for 'a'. So, you have to pass 'a' undefined argument. Then 'a' takes undefined(and it gets default value) and pass argument for 'b'.

// This is also another way to set default value ** This is more recommended and used in real life project.

function add({ a = 100, b = 200 }) {
  return a + b;
}
add({ b: 300 });
// 400
add({ a: 100 });
// 300

add(); // Error
add({}); // 300

let c = {a: 300, b: 400}; 
add(c); // 700
// If there is global variable declared and it has value for a, b then you can pass this variable as an argument.
// so the function add takes 300 for a and 400 for b like this add({ a = 100, b = 200 })
```

#Function Expression
Function is a **_special kind of value_** in JavaScript.

## Change Function declaration to Function expression
```js
// Function declaration
function sayHello() {
  console.log("Hello");
}

// Function expression
let showMessage = function () {
  console.log("Hello");
};

showMessage();
// Hello

// showMessage;  // it doesn't console.log Hello but show you the function.
// You need to add ()/parentheses after function name to call function.
```
The function is created and **assigned to the variable** explicitly, like any other value. No matter how the function is defined, it’s just a value stored in the variable showMessage.
The meaning of these code above is the same: "create a function and put it into the variable showMessage".

A function is a special value, in the sense that we can call it like showMessage().
But **_it’s still a value_**. So we can work with it like with other kinds of values.
We can copy a function to another variable
```js
function sayHello() { // (1) create
  console.log("Hello");
}

let messageFunc = sayHello; // (2) copy

messageFunc(); // Hello // (3) run the copy (it works)!
sayHello(); // Hello // this still works too
```

# Object initializer
```js
let a = 100;
let b = 200;

let c = { a, b }; // {a, b} => {a: 100, b: 200}
c;
// {a: 100, b: 200}

let obj = {
  a: a,
  b: b,
};
obj;
// {a: 100, b: 200}

// if the key and value name are the same in object, you can shorten them like this
let obj2 = {
  a,
  b,
};
obj2;
// {a: 100, b: 200}
```

# Block scope
Before talking about Block Scope,
### What's Block?
We’ve seen blocks used before in functions and 'if' statements. _**A block is the code found inside a set of curly braces '{ }'**_. Blocks help us group one or more statements together and serve as an important structural marker for our code.

A block of code could be a function, like this:
```js
const favouriteColour = () => {
  let color = 'black'; 
  console.log(color); // black 
}
```
**The function body is actually a block of code.

Block in an `if` statement:
```js
if (sun) {
  let color = 'red';
  console.log(color); // red
}
```
##So, what's the Block scope then?
When a variable is defined inside a block, it is only accessible to the code within the curly braces '{ }'. We say that variable has *block scope* because it is *only* accessible to the lines of code within that block.
Variables that are declared with block scope are known as *local variables* because they are only available to the code that is part of the same block.

```js
if (true) {
  let y = 10;
}
console.log(y); // error
// CANNOT read variable declared inside if statement from outside because there is block scope.

let yy = 100;
if (true) {
  let yy = 10;
  console.log(yy);
}
console.log(yy);
// 10  - console.logged from if statement block.
// 100 - console.logged from outside of if statement block. It references from let yy = 100 which is outer/global variable it can only read.

if (true) {
  const y = 10;
  console.log(y);
}
console.log(y);
// 10 - console.logged from if statement block.
// Uncaught ReferenceError: y is not defined // Error from console.log(y) written outside of if statement block. From outside of block, you cannot read local variable declared inside block which is if statement here.
```
## Exception: 'var' doesn't have block scope.
```js
if (true) {
  var y = 10;
  console.log(y);
}
console.log(y);
// 10
// 10
// 'var' doesn't have block scope!
// It doesn't create scope by block, you can access inside block.(Also can access inside loop)
// So, variables declared with 'var' can be accessed from outside of block and also can change it.
```

# Function Scope
var doesn't have block scope but it has function scope.
If code block is inside of function, var becomes function level variable. For that reason, even var can't be read from outside of function.
```js
// Things inside of function are unaccessible from outside of function. 
function 변수선언() {
  var nn = 1000;
}
console.log(nn);
//Uncaught ReferenceError: nn is not defined
//You cannot read var inside of function because there is function scope.
```

# Callback function
A callback function is a **_function passed into another function as an argument_**, which is then invoked inside the outer function to complete some kind of routine or action.
```js
function printData(data, log, dir) {
  console.log(data);
  console.dir(data);
}
let c = console.log;
let d = console.dir;
let array = [10, 20, 30];
printData(array, c, d);
// (3) [10, 20, 30]
// Array(3)
```

Write a function ask(question, yes, no) with three parameters:
- question: question text.
- yes: function to run if the answer is "Yes"
- no: function to run if the answer is "No"
The function should ask the question and, depending on the user’s answer, call yes() or no()
```js
function ask(question, yes, no) {
  if (confirm(question)) yes()
  else no();
}

function sayOk() {
  alert("You agreed.");
}

function sayCancel() {
  alert("You canceled the execution.");
}

// usage: functions sayOk, sayCancel are passed as arguments to function ask
ask("Do you agree?", sayOk, sayCancel);
```
The arguments sayOk and sayCancel of ask are called **_callback functions_** or just **callbacks**.
The idea is that <u>we pass a function and expect it to be “called back” later if necessary</u>. In our case, sayOk becomes the callback for “yes” answer, and sayCancel for “no” answer.

Function Expressions can be used to write the same function much shorter!
```js
function ask(question, yes, no) {
  if (confirm(question)) yes()
  else no();
}

ask(
  "Do you agree?",
  function() { alert("You agreed."); },
  function() { alert("You canceled the execution."); }
);
```

Here, functions are declared right inside the ask(...) call. **They have no name**, and so are called **_anonymous_**. <u>Such functions are not accessible outside of ask</u> (because **they are not assigned** to variables), but that’s just what we want here.


# Function and anonymous function.
```js
// Anonymous function expression
// The function doesn't have name but the function is assigned to variable. You can call the function with the variable name.
let add = function (a, b) {
  return a + b;
};

// Anonymous function expression
// The function doesn't have name but the function is assigned to variable. You can call the function with the variable name.
let add10 = function (a, b) {
  return a + b;
};
console.dir(add10);
// ƒ add10(a,b)

// Function has name. You can call the function with the function name.
function add20(a, b) {
  return a + b;
}

console.dir(add20);
// ƒ add20(a,b)

// Anonymous function. You cannot call this function because it doesn't have name and it's not assigned to variable either. There's no way to call this function.
console.dir(function (a, b) {
  return a + b;
});
// ƒ anonymous(a,b)
```

# Arrow function
An arrow function expression (previously, and now incorrectly known as fat arrow function) has a shorter syntax compared to function expressions and does not have its own this, arguments, super, or new.target. <u>**_Arrow functions are always anonymous_**</u>.

```js
let add30 = (a, b) => a + b;
add30(100, 100);
// 200

// if what's inside function is longer than one sentence of code, you must use curly brace '{ }'
let sum = (a, b) => {
  let result = a + b;
  return result;
};
sum(10, 24);
// 34

let sayHi = () => alert("Hello, everyone!");
sayHi();
// can use this without argument/parameter.
```
Find more about [Arrow Function](https://javascript.info/arrow-functions-basics)