본문 바로가기
생활코딩 학습일기(Web 기초)

14) javascript의 함수

by cuziam 2023. 4. 26.

일반적인 함수의 구조

함수란? 특정 동작을 수행하는 코드의 묶음. 아마 어렸을 때 함수를 공부했다면 이런 그림을 종종 봤을 것이다. input이 있고, input을 가지고 조작하는 어떤 연산과정이 있고, 결과적으로 어떤 output을 내놓는 이런 일련의 과정. 이것을 우리는 함수라고 배웠다. 프로그래밍에서 말하는 함수도 이와 유사하다.


함수의 정의와 호출

 

Javascript에서 함수는 어떻게 정의하고 어떻게 사용할까? 예시를 통해 한번 보자.

 

  1. 함수의 이름(Function name): 먼저 컴퓨터에게 함수의 이름을 알려줘야 한다. function키워드를 쓰고 그 뒤에 내가 붙이고 싶은 함수명을 붙인다.
  2. 매개변수(Parameter): 함수명 바로 뒤에 소괄호를 붙이고 그 안에 매개변수를 선언해준다. 매개변수는 함수 외부의 값이 대입되는 변수이다. 매개변수에 직접적으로 대입되는 값은 인자라고 부른다. x,y,z는 매개변수가 되고, 거기에 대입되는 값인 1,2,3는 인자이다. 만약 매개변수가 따로 필요 없다면 소괄호 내부에 아무것도 작성하지 않으면 된다.
  3. 실행문: 소괄호 바로 뒤에 중괄호를 쓰고, 매개변수에 전달된 값을 바탕으로 실행할 코드를 작성한다. 여기서 {console.log(x+y+z)}가 실행문에 해당된다.

이러한 일련의 과정을 함수를 정의한다고 부른다. 한번 정의된 함수는 함수명과 인자만 써준다면 어디서든 여러 번 호출해서 사용할 수 있다. 만약에 함수가 결과적으로 어떤 데이터를 반환하길 원한다면 return이라는 키워드를 실행문 끝에 작성하고 원하는 데이터를 작성한다. 이렇게 반환된 데이터는 다른 변수에 할당할 수 있다.

 


변수의 스코프(scope)

다음의 코드를 보자.

var x = 4; //전역변수(globoal variable) x와 y 정의
var y = 5;
function addNum(L, R) {
  var x = L; //함수 스코프를 가지는 지역변수(Local variable) x와 y정의
  var y = R;
  console.log(x + y); //지역 변수 x와 y를 더한 값을 콘솔창에 출력
}

addNum(8, 9); //17출력
console.log(x + y); //9출력

 

addNum(x,y)console.log(x+y)가 값이 다를까? 그것은 함수 내부의 x,y와 외부의 x,y가 다르기 때문이다. 이와 관련해서 스코프란 것에 대해서 알아 둘 필요가 있다.

 

모든 변수는 스코프를 가지고 있다. 스코프가 무엇일까?

scope란 말이 범위라는 말을 가지고 있는것에서 유추할 수 있듯이, 스코프란 변수의 유효영역이다. 한번 만들어진 변수들은 한번 만들어지고 프로그램이 종료될 때까지 계속 존재하는 것이 아니라 어떤 것들은 일찍 사라진다. 왜 일찍 사라지는 변수가 존재할까? 생각해보면 간단하다. 변수는 메모리를 차지 한다. 그런데 메모리 자원은 한정되어 있고, 사용하지 않는 메모리가 쌓이기만 한다면 비효율적이다. 메모리를 효율적으로 사용하기 위해서는 필요 없는 변수들은 일찍 사라질 필요가 있다.

 

스코프는 변수의 유효범위가 소스코드 전체인가 아닌가에 따라 크게 두가지로 나뉜다. 전자는 전역 영역(Global scope), 그리고 후자는 지역 영역(Local scope)라고 부른다. 그리고 각각의 스코프에 속하는 변수를 전역 변수(Global variable), 지역 변수(Local variable)이라고 부른다. 전역 변수들은 프로그래밍이 종료될 때까지 메모리를 차지하고 계속해서 존재하는 반면, 지역 변수는 그때그때 마다 활용되고 없어진다.

*변수영역(위키피디아): https://ko.wikipedia.org/wiki/%EB%B3%80%EC%88%98_%EC%98%81%EC%97%AD

 

변수 영역 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 컴퓨터 프로그래밍에서 변수 영역은 변수가 유효성을 갖는 영역을 가리킨다. 프로그램은 영역을 벗어난 변수를 가리킬 수 없다. 변수 영역을 지정하는 규칙은

ko.wikipedia.org

 

local scope는 프로그래밍 언어마다 조금씩 정해진 것이 다르다. C계열 언어는 변수들이 블록 영역(Block scope)을 가진다. 다시 말하면 블록(중괄호)마다 변수가 유효하고 블록이 다 실행되고 나면 그 변수는 메모리에서 사라진다. javascript의 변수인 var은 블록 영역을 따르지 않고 기본적으로 함수 영역(Function scope)을 따른다. 즉 함수마다 변수가 유효하고, 함수가 호출된 뒤에 종료되면 그 변수는 사라진다.

 

이제 왜 addNum(x,y)console.log(x+y)가 값이 다른지 알 수 있을 것이다. 만약 javascript에서 스코프가 블록 영역이 되는 변수를 사용하고 싶다면 var변수가 아니라 let을 사용한다. 변수가 아니라 블록 영역 상수를 원한다면 const를 사용하면 된다.

 

여기서 질문을 하나 더 해보자. 그럼 전역변수를 함수 내에서 다시 정의하는 방법은 없을까?

 

var x = 4; //전역변수(globoal variable) x와 y 정의
var y = 5;
function addNum(L, R) {
  x = L; //현재 스코프에 참조할 변수가 없으므로, 더 상위 스코프인 전역 스코프에 접근한다.
  y = R;//따라서 전역 변수의 값이 바뀌게 된다.
  console.log(x + y); //x와 y를 더한 값을 콘솔창에 출력
}

addNum(8, 9); //17출력
console.log(x + y); //17출력

그러고 싶다면 함수 내에서 var 키워드를 뺀다. 이렇게 되면 addNum함수 내부에 지역변수를 새로 정의한 게 아니기 때문에, 현재 스코프에서 참조할 x,y가 없다. 그래서 동일한 이름(식별자)을 가진 다른 변수를 찾는데, 해당 스코프 보다 더 상위 스코프를 가지는 전역변수 x, y에 접근한다. 그럼 이렇게 결과적으로 addNum(x,y)console.log(x+y)는 같은 값을 출력한다. 반대로 상위 스코프에서 유효한 변수를 하위 스코프에서 재정의할 수 있을까? 그것은 불가능하다.

*javascriptscope에 관한 정리(영문): https://www.tutorialsteacher.com/javascript/scope-in-javascript

 

Scope in JavaScript

Scope in JavaScript Scope in JavaScript defines accessibility of variables, objects and functions. There are two types of scope in JavaScript. Global scope Local scope Global Scope Variables declared outside of any function become global variables. Global

www.tutorialsteacher.com

읽기 어렵지 않으므로 한번 보는 걸 추천한다.


호이스팅(Hoisting)

 

왜 위의어떤 프로그래밍 언어든, 소스코드들은 원칙적으로 위에서부터 차례대로 실행된다. 그래서 컴퓨터에게 필요한 데이터나 함수들은, 소스코드 앞부분에 미리 선언해 놓는다. 만약에 함수를 정의하기 전에 함수를 호출하면 어떻게 될까? 당연히 컴퓨터는 무엇을 하라고 하는지 몰라서 에러가 발생한다.

 

addNum(4, 5);//오류가 발생하지 않고 9를 출력한다.
function addNum(L, R) {
  var x = L;
  var y = R;
  console.log(x + y);
}

 

근데 위의 코드는 정상적으로 실행될까? Javascript는 다른 프로그래밍 언어들과 달리 함수를 호출하는 코드를 먼저 작성하고 나중에 선언해도 실행이 가능하다. 그 이유는 javascript가 내부적으로 문법을 검사하고 선언부만 따로 소스코드의 앞으로 끌어올려서 실행하기 때문이다. 정확히 말하면 어떤 변수나 함수의 선언부만 자신의 스코프에 해당하는 부분의 최상단으로 끌어올려지게 된다.

 

이러한 컨셉을 호이스팅(hoisting)이라고 부른다. hoist는 밧줄과 같은 것으로 물건을 끌어올린다는 의미를 지닌다. 동시에 그러한 일을 하는 장치를 말하기도 한다. 여기서 유의해야 할 것은 정의가 아닌 선언만 따로 빠져서 호이스팅 된다는 점이다. 예시를 보고 호이스팅이 어떤 순서로 실행되는지 알아보자.

 

console.log(x + y); //NaN 출력
addNum(4, 5); //NaN 출력
function addNum(L, R) {
  console.log(x + y);
  var x = L;
  var y = R;
}
var x = 7;
var y = 9;

위쪽의 코드는 왜 값들을 출력하지 못할까?

  1. 먼저 함수와 변수 각각의 선언만 코드 맨 앞에 호이스팅 된다. 즉 변수의 선언이 함수의 선언보다 더 상위에 작성된다. 그리고 변수의 정의는 원래 있던 자리에 그대로 남는다.
  2. 그 후에 함수 실행문 내부에서도 1과 똑같은 과정을 밟는다. 다만 스코프가 함수 영역이므로 그 영역을 벗어나지 않는다.
  3. 결과적으로 변수들이 선언은 되었으나 각각의 console.log 함수가 호출된 후 그 값이 정의되었다. 따라서 호출된 console.log 함수들은 NaN(Not a Number)이라는 결과를 출력한다.

 

우리가 실제 코드를 작성할 때, 호이스팅을 믿고 아무렇게나 코드를 작성하는 것은 그다지 좋지 않다.

*호이스팅으로 인해 함수의 호출이 함수의 정의보다 앞서 실행될 수 있으므로, 함수 선언식보다는 함수 표현식을 권장한다고 한다.

 

*javascripthoisting에 관한 정리(영문): https://www.tutorialsteacher.com/javascript/javascript-hoisting

 

Hoisting

JavaScript Hoisting Hoisting is a concept in JavaScript, not a feature. In other scripting or server side languages, variables or functions must be declared before using it. In JavaScript, variable and function names can be used before declaring it. The Ja

www.tutorialsteacher.com

javascript – Hoisting(호이스팅)의 관해 알아보자: https://velog.io/@surim014/JavaScript%EC%97%90%EC%84%9C%EC%9D%98-Hoisting%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80

 

JavaScript - Hoisting(호이스팅)에 대해 알아보자

호이스팅 (Hoisting) 사전적 정의 : 끌어 올리기 JavaScript에서의 Hoisting : 변수의 정의가 그 범위에 따라 선언과 할당으로 분리되는 것을 의미한다. 즉, 변수가 함수 내에서 정의되었을 경우, 선언부

velog.io

Javascript의 함수에 대해서는 일단 여기까지만 다루려고 한다. 함수의 정의와 호출 부분은 큰 어려움 없이 학습할 수 있을 것이다. 사실 하지만 스코프와 호이스팅에 관해서 깊이 이해할 필요가 있긴하다. 하지만 이 카테고리의 글들은 프로그래밍 왕초보자를 대상으로 하였기 때문에 이 부분은 참고링크로 남긴다.