본문 바로가기
JavaScript

[JavaScript] Function Note

by 배잼 2022. 2. 5.

모던 자바스크립트 Deep Dive 12장을 읽으며 정리한다.

"Function Declarations vs Function Expressions"

Just a Style!... But?

함수 선언문은 다음과 같다.

function add(x,y){
	return x+y;
}

함수 표현식은 함수 리터럴로 생성한 함수 객체를 변수에 할당하는 것이다. 다음과 같다.

var add = function foo(x,y){
	return x + y;
};

이때, 함수를 호출할 때는 함수 이름이 아니라 함수 객체를 가리키는 식별자를 사용해야 한다! 따라서 만약 위 코드에서 add( 1, 2)를 콘솔에 찍으면 정상적으로 출력되지만, foo로 찍으면 작동하지 않는다. 함수 이름은 함수 몸체 내부에서만 유효한 식별자기 때문이다! (그렇다면 함수 선언문은 어떻게 된 걸까? 자바스크립트가 자동으로 할당해주는 거다.)

함수 이름은 함수 몸체 내부에서 유효하므로, 만약 위 함수를 재귀적으로 사용하고 싶다면 함수 안에는 foo를 쓸 수 있다.

함수 표현식에서는 함수 이름을 지울 수 있다. foo를 지우는 셈이다. 이를 익명 함수라고 한다. 보통은 이름을 생략한다.

  1. 코드를 실행하기 전에 함수를 우선 선언한다→ hoisting
console.log(add(2,5)); // 7 
console.log(foo(2,5)); //foo is not a function

function add(x,y){
	return x+y;
}

var foo = function (x,y){
	return x + y;
};

function expression으로 정의한 함수, 그리고 Function Declaration으로 정의한 함수는 생성 시점이 다르다. 모든 decleration은 runtime 이전에 자바스크립트 엔진에 의해 실행된다. 따라서 decleration으로 함수를 정의하면 런타임 이런제 함수 객체가 먼저 생상된다! 따라서 선언문 이전에 먼저 함수를 참조할 수도 있고, 호출할 수 도 있다. 이를 함수 호이스팅(hoisting)이라고 한다.

  • 변수 호이스팅은 undefined로 먼저 초기화되어, 선언문 이전에 불러내면 undefined로 평가된다. 그러나 함수의 경우 선언문 이전에 호출하면 호출이 가능하다!
  • 이때, function expression으로 정의한 함수는 변수 호이스팅이 발생한다. 따라서 할당문이 실행되는 시점함수 객체가 된다**.** 그 이전에 참조하면 undefined로 평가된다.

Function 생성자 함수 (constructor function)

var add = new Function('x', 'y', 'return x+y');

Arrow functions

//Function Declaration

function getRandomNumber(){
  const randomNumber = Math.floor( Math.random() * 6 ) + 1 ;
  return randomNumber;

}

//Function Expression

const getRandomNumber = function() {
  const randomNumber = Math.floor(Math.random() * 6 ) + 1;
  return randomNumber;
};

//Arrow function

const getRandomNumber = () => {
  const randomNumber = Math.floor(Math.random() * 6 ) + 1;
  return randomNumber;
}; 

hoisted 되지 않는다. 선언되기 전에 실행하면 에러가 난다.

값의 전달

function change(primitive , obj) {
	primitive += 10;
	obj.name = 'cherry';
}

let num = 10;
let fruit = { name : 'pear'};

console.log(num, fruit); //10 {name: 'pear'}
change(num, fruit);
console.log(num, fruit); // 10 {name: 'cherry'}

객체는 바뀌는 걸 알 수 있다! 왜냐하면 객체는 참조 값이 복사되어 매개변수에 전달된다. 따라서 의도치 않은 객체의 변경이 일어날 수 있다. 해결 방법으로 객체를 불변 객체(immutable object)로 만드는 게 가능하다.

default function parameter

function multiply(a, b = 1) {
  return a * b;
}

console.log(multiply(5, 2));
// expected output: 10

console.log(multiply(5, undefined ));
// expected output: 5

즉시 실행 함수(Immediately-invoked function expression)

함수 정의와 동시에 즉시 호출되는 함수를 즉시 실행 함수라고 한다.

  • 익명 즉시 실행 함수
(function () {
	var num1 = 3;
	var num2 = 1; 
	return num1 + num2;
}());
  • 가명 즉시 실행 함수
(function foo() {
	var num1 = 3;
	var num2 = 1; 
	return num1 + num2;
}());

의문 : 함수는 재사용하기 위한 건데 왜 즉시 실행 함수를 사용하는 걸까? 이는 다음 포스트에서 다시 적기로 하겠다.

콜백 함수

자바스크립트의 비동기를 공부할 때 콜백함수가 항상 대두된다! 콜백 함수는 함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수다. 고차 함수(Higher-Order Function, HOF)는 매개변수를 통해 함수의 외부에서 콜백 함수를 전달받은 함수다.

예제를 보자.

function repeat(n, f){
    for (let i = 0; i<n; i++){
        f(i)
    }
}

const allNum = function(i){
    console.log(i); 
};

repeat(5, allNum); //0 1 2 3 4 

const oddNum = function(i){
    if (i % 2) console.log(i);
};

repeat(5, oddNum); // 1 3

고차 함수는 콜백 함수를 자신의 일부분으로 합성해서 사용한다. 즉, 이런 방식이면 매번 함수를 새롭게 정의할 필요 없이 콜백 함수만 바꿔주면 된다!

위 코드에서 익명 함수도 사용할 수 있다.

repeat(5, function(i){
    if (i % 2) console.log(i);
}); //1 3 

이는 이벤트 처리, 비동기 처리, 배열 고차 함수에서 사용된다.


ref

호이스팅 - 용어 사전 | MDN

기본값 매개변수 - JavaScript | MDN

댓글