[Javascript] C와 비교하며 학습하는 Javascript (4)

Suh, Hyunwook·2021년 6월 13일
0
post-thumbnail

오늘의 학습자료 : 자바스크립트 12 - 함수(Function)

1.함수 호이스팅(Funciton Hoisting)

호이스팅(Hoisting)은 var 선언문, function 선언문 등 모든 선언문이 해당 범위(Scope)의 선두로 옮겨진 것 처럼 동작하는 특성을 말합니다. 소스코드 순서상 함수가 뒤에 있더라도, 변수값에 함수를 담을 수 있다는 것입니다.

이 방식이 가능한 이유는, C에서는 소스코드 순서대로 Compile되기 때문에 호이스팅 개념이 들어갈 수 없습니다. run 함수 내에 있는 call함수 호출에 에러가 나는 부분을 참고하면 이를 알 수 있습니다.

JS에서는 스크립트가 로딩되는 시점에 바로 초기화하고 이를 VO(variable object)로 저장하기 때문입니다. 그래서 호이스팅 기능이 있는 경우, 아래 처럼 구현이 가능합니다.

var res = square(5);

function square(number) {
  return number * number;
}

물론, 아래와 같은 예외도 있습니다.

var res = square(5); // TypeError: square is not a function

var square = function(number) {
  return number * number;
}

만약 함수가 선언문의 형식이 아니라, 표현식일 경우, 스크립트 로딩시점이 아니라, Run-time 시점에 변수를 읽기 때문에 호이스팅되지 않습니다. 얼핏 보면 호이스팅 개념은 굉장히 편리한 부분처럼 보이지만... 인생사가 다 그렇듯이 편리하면 반드시 부작용이 있는 경우가 많네요. 🤔

Poiema 강의 내용 중,더글러스 클락포드의 말을 인용하면 함수를 선언문으로 정의 시, 선언문이 많아지면 인퍼프리터가 너무 많은 코드를 Variable Object에 저장하므로 속도가 느려지는 부분을 지적하기도 했죠.

2. 독특한 함수의 개념: 일급 객체, Return

일급객체의 특성은 다음과 같습니다.

- 무명의 리터럴로 표현이 가능
- 변수나 자료구조(객체, 배열 등)에 저장가능 
- 함수의 매개변수에 전달 가능
- 반환값으로 사용 가능
// 1. 무명의 리터럴로 표현이 가능하다.
// 2. 변수나 자료 구조에 저장할 수 있다.
var increase = function (num) {
  return ++num;
};

var decrease = function (num) {
  return --num;
};

var predicates = { increase, decrease };

// 3. 함수의 매개변수에 전달할 수 있다.
// 4. 반환값으로 사용할 수 있다.
function makeCounter(predicate) {
  var num = 0;

  return function () {
    num = predicate(num);
    return num;
  };
}

var increaser = makeCounter(predicates.increase);
console.log(increaser()); // 1
console.log(increaser()); // 2

var decreaser = makeCounter(predicates.decrease);
console.log(decreaser()); // -1
console.log(decreaser()); // -2

C를 처음으로 학습한 이후 보는 위의 코드는 매우 헷갈렸습니다. 단순히 절차대로 읽으면 이해하기 매우 까다롭네요..😵‍
호이스팅 및 함수가 매개변수로 들어가 있는 코드를 읽는 방식이 어려워, 나름대로 생각한 방법은 리턴값에 집중하기. 입니다.
위 코드의 경우 predicate에 담긴 값을 ++num, --num으로 생각한 뒤에, makeCounter 함수는 어차피 호이스팅 되어있기 때문에, 건너뛰고, increaser, decreaser에서 호출한 값이 무엇인지 보는 것이죠.
increaser에는 predicates.increase 즉, ++num을 매개변수로 보냈고, makeCounter 내에 정의된 var num = 0에 ++num처리를 해주라는 말로 이해할 수 있습니다. 위 코드가 간단해서 망정이지..여러번해서 숙달하는 법 밖엔!😏

리턴(Return) 의 경우에도, 특이한 녀석이 있습니다. 앞선 포스팅인 [포인터는 왜 배우는 것인가?][https://velog.io/@hw8129/CC-%ED%8F%AC%EC%9D%B8%ED%84%B0%EC%9D%98-%EC%82%AC%EC%9A%A9-21.03.23]에서 언급한 바가 있는데, C에서는 Return 값을 1개 이상 반환하지 못합니다. 이 때문에, 전역변수를 적극 활용하여, 함수 내에서 수정해주는 방식이 많습니다. 즉, 전역변수를 쓰냐 마냐도 C에서는 중요하게 고려해야할 사항입니다.

function getSize(width, height, depth) {
  var area = width * height;
  var volume = width * height * depth;
  return [area, volume]; // 복수 값의 반환
}

console.log('area is ' + getSize(3, 2, 3)[0]);   // area is 6
console.log('volume is ' + getSize(3, 2, 3)[1]); // volume is 18

JS에서는 return 값이 두 개가 가능합니다! 심지어 배열값 호출하는 것 마냥, getSize(3,2,3)[0]과 같이 사용도 가능하죠. '엄격함'과 '엄격함이 주는 안락함' 그리고, '편리성, 자유로움'과 '편리성이 주는 부작용'. 일장일단은 프로그래밍에도 존재하는 진리인거 같습니다.

추후에는 함수 객체의 다양한 프로퍼티에 대해서 다뤄보려고 합니다.

0개의 댓글