Javascript Functions & Scope

  • Functions 은 항상 값을 반환한다.
    • return 값이 존재하지 않으면 undefined 를 반환한다.
  • Functions 은 오브젝트이다.
  • Scope 에는 두 가지 종류의 scope 가 존재한다.
    • Global Scope
    • Local Scope
  •  

Function Declaration & Function Expressions

  • Function Declaration 은 이름에 기반한 함수로 정의된다.
    • 함수는 선언되어 있기 때문에 순서에 상관없이 호출될 수 있다.
  • Function Expressions 는 익명함수로 정의된다.
    • "function" 구문으로 시작하지 않는다.
  • 익명함수는 함수에 이름이 존재하지 않는다. 따라서 정의되기 이전까지 사용할 수 없다.
    • 변수에 함수를 할당하는 형태이다.

 

named function Declaration

function say(){
    console.log("Hello");
}

say();  // Hello

 

anonymous function Expression

let say = function(){
    console.log("Hello");
}

say();    // Hello

 

anonymous function Expression (Error)

초기화 되기 전에 호출하면 스크립트 오류 발생

// Uncaught ReferenceError: Cannot access 'say' before initialization
say();

let say = function(){
    console.log("Hello");
}

 

Self Invoking function Expression

// 즉시 실행된다.
(function say() {
    console.log("Hello");
})();

 

anonymous function 의 아우터 및 이너 Error 발생코드

let number1 = 10;
let number2 = 20;

let calculate = function add(num1, num2){
    return num1 + num2;
}

let valueOfOuter = calculate(number1, number2);
console.log(valueOfOuter); // 30 

let valueOfInner = add(number1, number2);
console.log(valueOfInner);  // Uncaught ReferenceError: add is not defined
  • calculate() 에서의 함수호출은 무탈하게 호출되지만 내부적으로 add() 함수는 에러가 발생한다. 내부적으로 add()  함수를 이용하기 위해선 아래와 같이 사용해야 한다.

anonymous function 의 아우터 및 이너 변경사항

let number1 = 10;
let number2 = 10;

let calculate = function add(num1, num2){

    if(num1 === num2){
        return add(num1 + num2, num2);
    }

    return num1 + num2;
}

let value = calculate(number1, number2);
console.log(value); // 30 

 

Arrow function

  • function 키워드를 대신해서 화살표를 사용하여 간격하게 함수를 표현할 수 있다.
  • this, arguments, super 등을 바인딩하지 않는다.
let say = () => {
    console.log("Hello");
}

say();  // Hello

 

Parameters & Arguments

 

Parameters

  • 일반적으로 함수를 작성하고 함수에 매개변수를 전달한다.
const param1 = "DOG";
const param2 = "CAT";

function twoParams(param1, param2){
    console.log(param1 + ", " + param2);
}

twoParams(param1, param2);  // DOG, CAT

/**
 * param1 과 param2 를 파라미터라고 부른다.
 */

 

Arguments

  • 매개변수를 통해 전달받은 함수 내 실질적인 값이다.
const param1 = "DOG";
const param2 = "CAT";

function twoParams(param1, param2){
    console.log(param1 + ", " + param2);
}

twoParams(param1, param2);  // DOG, CAT

/**
 * DOG 와 CAT 이 아규먼트 즉 인수이다.
 */

 

Function Scope & Block Scope

  • ECMA 6 (이하 es6) 가 나오기 이전에는 var 키워드를 통해서 변수를 선언하거나 초기화하였다.
  • var 키워드는 변수의 영역이 모호하다.

function scope (var)

var name = "PARK";

function chanageName(){
    var name = "KIM";
    console.log("inner :", name);
}

chanageName();     
console.log("outer :", name);

// inner : KIM
// outer : PARK

 

block scope : if statement (var)

/**
 * var 키워드 사용
 */
 
var name = "PARK";

if(true){
	/** if 조건문은 새로운 scope 를 생성하지 않는다. **/
    var name = "KIM";	/** global scope **/
    console.log("inner :", name);
}

console.log("outer :", name);

// inner : KIM
// outer : KIM

if 조건문에서 중괄호 "{}" 로 묶어놓은 영역 내의 변수 때문에 바깥의 값이 변함을 확인할 수 있다. 이러한 값의 변환은 개발자에게 혼란을 주기 충분하다. 위의 사례는  es6 부터 도입된 let 키워드로 해결할 수 있다.

 

block scope : if statement (let)

/**
 * let 키워드 사용
 */

let name = "PARK";

if(true){
    let name = "KIM";	/** local scope **/
    console.log("inner :", name);
}

console.log("outer :", name);

// inner : KIM
// outer : PARK

let 을 통해 외부와 내부의 값이 따로 설정되는 것을 확인할 수 있다. 따라서 이전에는 function scope 로 이용되어왔다면 let 의 등장으로 block scope 가 가능하게 된 것이다.

 

loop

  •  반복문 내에서 선언되는 초기값, 조건값, 증감연산자 등을 var 키워드 또는 let 키워드로 선언했을 때 결과값이 달리 나온다. 아래의 예시를 확인하자
var array = [];

for (var i = 0; i < 3; i++){
    array.push(() => console.log(i));
}

array.forEach(f => f());
// 3 3 3
for (let i = 0; i < 3; i++){
    array.push(() => console.log(i));
}
  • 첫번째 코드는 3 3 3 이 찍힌다.
    • 반복문은 scope 가 아니기 때문에 저렇게 값이 나타나는 것이다.
  • 두번째 코드는 1 2 3 이 찍힌다.

정리

var 는 function scope 로 구분되기 때문에 값에 대한 동기화 문제가 발생한다. 반면에 let 은 block scope 인 중괄호에 의해서 구분되기 때문에 var 보다는 조금 더 엄격한 조건에서 값을 조작하는데 안전성이 있다.

 

reference

모든 자바스크립트 개발자가 알아야할 33가지 개념

https://scotch.io/tutorials/understanding-scope-in-javascript#toc-introduction

Posted by doubler
,