Pandaman Blog

[JS] Javascript의 Function (함수) 본문

Front end/Javascript

[JS] Javascript의 Function (함수)

oyg0420 2020. 1. 11. 21:35

Javascript Function

자바스크립트의 모든 함수는 Function 객체입니다.
JavaScript에서, 함수는 다른 객체처럼 속성 및 메서드를 가질 수 있기에 일급(first-class) 객체입니다.

MDN 문서를 확인해보면 Function 객체는 일급 객체(first-class)라고 정의합니다. 그렇다면 일급 객체라는 것이 무엇인지 확인해보겠습니다.

  • 변수나 데이터 구조안에 담을 수 있다.
  • 파라미터로 전달할 수 있다.
  • 리턴 값으로 사용할 수 있다.

간단한 예제를 통해 알아보겠습니다.

// 1. 변수에 함수를 할당
const multiply = function(a, b){ return a * b };
console.log(sum(1, 2)); // 3

// 2. 파라미터로 전달
const sum = function(a, b){ return a + b};
sum(2, multiply(2, 3)); // 8

// 3. 리턴값으로 사용
const square = function(a) { 
    return multiply(a, a);
}
console.log(square(3)); // 9

위 예제를 통해 함수가 일급 객체란 이유에 대해 확인할 수 있습니다.

함수 정의하기

함수를 정의하는 방법에는 여러 가지 방법이 있습니다.

1) 함수 생성자

Function 객체는 new 연산자를 사용하여 함수를 정의할 수 있습니다.
매개변수와 함수 본문을 문자열로 정의합니다.

참고로 함수 생성자로 생성한 함수 객체는 함수를 생성할때 구문분석(Parsing) 을 수행합니다. 반면 함수 표현식이나 함수 선언문으로 함수를 정의하고 코드 내에서 호출한 경우 나머지 코드와 함께 구문분석(Parsing) 을 하게 됩니다. 따라서 함수 생성자로 함수를 생성하는것은 비효율적입니다.

const sum = new Function('a', 'b', 'return a + b');

사실 함수 생성자로 함수를 정의하는 일은 거의 없습니다.

2) function 선언문(function declaration)

이름과 매개변수 함수 본문(statements)을 아래와 같이 표현할 수 있습니다.

예제를 통해 알아보겠습니다.

function name([param[param, ]]) {
  statements
}
// 이름이 sum, 매개변수가 a, b, 본문이 a + b 인 함수
function sum(a, b) {
    return  a + b; 
}

위의 예제는 함수선언의 예입니다. 이름은 sum, 바디에는 return a + b 를 갖는 함수를 선언했습니다.

3) function 표현식

함수표현식은 함수을 선언하는 방법의 한가지입니다.
함수표현식과 함수 선언문의 차이점은 함수 표현식은 함수 이름의 생략이 가능하다는 점입니다.

예제를 통해 알아보겠습니다.

function([param[param, ]]) {
  statements
}

// 실제로 사용하는 방법
const sum = function(a, b) { return a + b };
sum(1, 3); // 4

함수 표현식을 쓰고 그 결과를 변수 sum에 할당한 예제입니다. 식별자 sum이 이 함수를 가리키고, sum(1, 2); 로 호출할 수 있습니다.

함수 표현식은 함수 선언과 달리 함수 hoisting(끌어올리다)가 되지 않습니다. hoisting에 대해 아래에서 살펴볼텐데요. 차이점이 무엇인지 간단히 예제를 통해 확인해보겠습니다.

/*
 함수 표현식
*/
console.log(f1); // VM485:1 Uncaught ReferenceError: f1 is not defined

f1(); // VM485:1 Uncaught ReferenceError: f1 is not defined

const f1 = function(){
  console.log('can not hoisting');
}


/*
 함수 선언문
*/
f2(); // 'can hoisting'

function f2(){
    console.log('can hoisting');
}

위 예제와 같이 함수 표현식으로 생성한 함수를 정의되기 전에 호출하면 에러를 발생시킵니다. 하지만 함수 선언문으로 생성된 함수는 함수 정의 전에 실행이 가능하다는 차이점이 있습니다.

더 자세한 사항은 Function Hoisting에서 확인하겠습니다.

5) arrow function

Arrow function Expression 은 ES6 문법으로 function Expression 에 비해 짧고, 항상 익명입니다.

// function 표현식
const sum = function(a, b) { return a + b };
const square = function(a) { return a * a };

// Arrow function
const sumWithArrow = (a, b) => (a + b);
const squareWithArrow = a => (a * a );

const squareWithArrowReturn = a => { return a * a };

function 표현식과 비교하면 function이 없어졌습니다. 그리고 return문이 제거되었습니다.
하지만 {}가 있다면 return문이 필요합니다.

일반적인 함수와 Arrow function과의 또 다른 차이점이 있습니다.
일반 함수는 함수가 어떻게 호출되느냐에 따라 this가 동적으로 결정됩니다. 하지만 arrow function은 자신의 this를 갖지 않고, 언제나 자신을 둘러싸고 있는 객체의 this를 상속받습니다.

아래 예제를 통해 알아보겠습니다.

let cow = {
      sound: '음매',
      play: function () {
          console.log(this) // 1번
          setTimeout(function () {
            console.log(this) // 2번 
            console.log(this.sound); // 3번 
        }, 1000);
    }
}

console.log(cow.play()); 
// 1번 {sound: "음매", play: ƒ}
// 2번 Window
// 3번 undefined

cow 객체 play의 내부 함수 this는 window 객체입니다. window객체에는 sound라는 변수가 없기 때문에 this.sound는 undefined가 됩니다. 어떻게 하면 play의 내부 함수의 this가 cow객체를 나타나도록 할 수 있을까요??? 바로 bind() 함수를 사용하면 쉽게 해결할 수 있습니다. bind()는 객체와 함수를 묶어주는 기능을 합니다.

let cow = {
      sound: '음매',
      play: function () {
          setTimeout(function () {
            console.log(this) 
            console.log(this.sound);
        }.bind(this), 1000);
    }
}

console.log(cow.play()); 
// {sound: "음매", play: ƒ}
// "음매"

setTimeout을 bind(this)를 통해 this가 cow객체임을 나타내고, this.sound에 접근한 것을 확인할 수 있습니다.
하지만 매번 bind()를 사용하기 귀찮을 수 있습니다. 이 경우 arrow function을 사용하면 됩니다.

let cowWithArrow = {
      sound: '음매',
      play: function() {
          setTimeout(() => {
            console.log(this); // {sound: "음매", play: ƒ}
            console.log(this.sound); // '음매'
        }, 1000);
    }
}

cowWithArrow에서 this.sound가 원하는 데이터로 출력된 이유는 arrow function의 this는 상위 스코프의 this를 가리키기 때문입니다. 그러한 이유로 play함수를 arrow function으로 사용하지 않은 이유입니다. arrow function으로 사용했다면 this는 widow 객체를 가리킬 것입니다.

 

파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음

Comments