본문 바로가기
JavaScript

2021.04.13 JavaScript 함수

by 해맑은 코린이 2021. 4. 13.

 

2021.04.13_JavaScript 함수_정리노트

 

 

 

오늘은 ko.javascript.info/ 에서 참고해서, 함수 혼자 헷갈리는 거 혼자 정리해보기.

 

함수는.. 정말 태생 문과인 나에겐 항상 꺼려지는 개념인 것 같다.

 

그래도 나중에 비동기 처리 과정에 대해서, 그리고 그를 유연히 다루기 위한 개념들을 좀 더 이해하기 위해 먼저 정리하는, 기본 함수에 대한 나의 정리.

 

 

 


먼저, 기본적인 것들을 혼자 주절주절 하면서 정리.

 

함수의 이름은 무엇을 하는지 직관적으로 알 수 있어야 하며, 동작을 수행하기 때문에 주로 동사로 이루어 진다.

 

 

코드는 혼자 칠 수는 있지만, 평생 혼자 하지 않아!!! 그렇기 때문에, 은연중..? 암묵적..? 에 개발자들이 정해놓은 규칙 같은 것이 있다.

이는 지키지 않아도 되지만, 하나의 규칙 같은 것들이라 나중에 우리가 제대로 된 개발을 하게 된다면, 그리고 그 코드를 보여줄 수 있을 만큼의 퀄리티가 된다면, 가독성, 편리성 등등 여러 이유로 이런 기초들이 나중에 도움이 될 것 같기 때문에, 나는 이런 규칙들을 찾아서 해보는 것도 좋아한다. 그리고 솔직히 이름 같은 거 나 혼자 나중에 짓기 귀찮잖 ㅎ

 

 

쨋든, 자바스크립트의 함수에서도 이러한 규칙? 들이 있는데, 접두어들을 살펴보자면,

 

show >> 무언가를 보여주는 함수

get >> 무안가를 반환하는 함수

calc >> 무언가를 계산하는 함수

create >> 무언가를 생성하는 함수

check >> 무언가를 확인, 불린값을 반환하는 함수

 

 

 

깔끔하고, 이해하기 쉬운 코드를 작성하려면, 전역 변수 대신, 지역변수와 매개 변수를 활용하라.

 

저번 포스팅에서 var 에 대한 위험성을 경고하면서, 정말 크게 깨달은 개념.

꼭 편리성, 가독성이 아니더라도 이는 실수를 줄이는 중요한 개념이라고 생각함.

 

 

 

return 이 없거나, return 만 있는 함수의 경우는 undefined 를 반환한다.

 

function doNothing() { 



}

 

alert( doNothing() === undefined ); // true




function doNothing() {

 return;

  }



alert( doNothing() === undefined ); // true

 

 


 

 

그다음은 함수 표현식.

 

 

자바스크립트의 경우, 함수는 괄호가 없으면 해당 함수 실행이 되지 않음.

 

 function sayHi(){
     alert("hi!")
 }

alert(sayHi()); // 괄호가 없으면 함수 그자체가 문자열로 변환되어 실행.

 

 

함수는 값이다. 따라서 함수도 값처럼, 변수에 할당, 복사, 선언을 할 수 있다.

 

 

//함수 선언

function sayHi(){
	alert("Hi!");
}

//변수 func에 함수 복사

let func = sayHi;   // *주의 : 변수에 해당 함수 그 자체를 복사할 때는, 함수의 이름만 적을 것.
                    // 여기서 sayHi()로 복사하게 되면, 함수 자체가 복사되는 것이 아니라, 
                    // 함수의 호출 결과, 즉, 함수의 반환 값 그 자체를 복사하게 됨. ( 여기서는 "Hi!" )
   
// 복사한 함수를 실행 하기

func();       // 함수 그 자체를 복사했으니까, 여기서는 괄호를 붙여서 실행 시켜주면 됨!

sayHi();      // 본래 함수도 정상적으로 작동함.

 

 

함수를 생성하고, 변수에 값을 할당하는 것처럼 함수도 변수에 할당하여 복사, 저장할 수 있다. 

이를 함수 표현식이라고 한다.


 

 

함수 선언문 vs 함수 표현식

 

//함수 선언문

function sayHi(){
  
  alert ("Hi!");

}

sayHi();


//함수 표현식


function sayHi(){
  
  alert ("Hi!");

}

let func = sayHi;

func();

 

이 둘의 차이는 자바스크립트 엔진이 언제 함수를 생성하는지에 있다.

 

함수 선언문에서 함수는 주요 코드 흐름 중간에 독자적인 구문 형태로 존재한다. 그렇기 때문에, 전역 함수 선언문은, 스크립트 어디에 있느냐에 상관없이 어디에서든 사용이 가능하다.

그와는 다르게, 함수 표현식은 실제 코드의 실행 흐름이 해당 함수에 도달했을 때, 함수를 생성한다. 따라서 코드의 실행 흐름이 해당 함수에 도달했을 때부터 사용할 수 있다.

 

이게 가능한 이유는, 자바스크립트의 내부 알고리즘 때문.

자바스크립트는 스크립트를 실행하기 전, 준비 단계에서 전역으로 선언된 함수 선언문을 찾고, 해당 함수를 실행시킨다. 

스크립트가 진짜 실행되기 전인 준비 단계, 즉 "초기화 단계" 에서 함수 선언문으로 정의한 함수가 먼저 생성 된다.

초기화 단계가 모두 처리되고 나면, 스크립트는 그제서야 실행 된다.

 

 

//함수가 선언되기 전에 함수를 호출해도 정상적으로 작동.

sayHi("korin"); // Hi, korin!

function sayHi(name) {
  alert( `Hi, ${name}!` );
}



sayHi("korin"); // Uncaught ReferenceError: sayHi is not defined 
               

let sayHi= function (name) {
  alert( `Hi, ${name}!` );
}


 

그렇기 때문에, 전역 함수 선언문으로 실행된 함수는, 스크립트의 어디서든 접근할 수 있다.

 

 

 

이게 이 둘의 가장 큰 차이라고 볼 수 있는데, 그러면 함수 선언식은 함수 그 자체이기 때문에, 왼쪽에 변수로 할당하는 것보다 가독성도 좋고, 순서에 상관 없이 호출할 수 있어, 코드를 짜는데도 더 편리한 것 같은데 함수 표현식은 왜 필요할까?

 

 

필요한 이유는, 스코프의 차이로 설명할 수 있다.

 

Scope 를 우리말로 변역하면, '범위' 라는 뜻을 가지고 있다. 즉 스코프란, '변수에 접근할 수 있는 범위' 라고 할 수 있다.

 

자바스크립트에서 스코프는 2가지의 타입으로 나뉜다.

 

전역 스코프지역 스코프.

대표적인 지역 스코프로는 바로 함수가 있다. 자바스크립트에서는 함수를 선언하면 함수를 선언할 때마다 새로운 스코프를 생성하게 된다. 

그러므로 함수 몸체에 선언한 변수는 해당 함수 몸체( 블록 :  중괄호 ({}) , for,if ,while 범위  ) 안에서만 접근이 가능하다. 이를 함수 스코프라 한다.

그러니 함수 스코프는 지역 스코프의 대표적인 예이다.

 

 

 

어.. 뭐지 전역.. 이랬다가 지역이랬다가... 내가 아까 이래서 함수 선언문 앞에 전역 강조한 거 ㅇㅇㅇ

 

 

헷갈릴 수 있겠지만, 함수를 전역으로 선언하게 되면, ( 블록 없이 ) 모든 곳에서 호출이 가능 하지만, 블록 단위로 쓰일 때는 함수 선언문은 지역 스코프라는 것 잊지 말자. 

 

하지만, 일반적으로 그냥 자바스크립트 파일에 함수 선언문을 사용하게 되면, 전역이든, 지역이든, 브라우저에 잘 작동이 될테다.

그럼 왜 어떻게 함수가 지역 스코프가 된다는거지 ? 

내가 참고한 문헌의 이름을 다시 살펴보면 '모던' 자바스크립트임. 그러니 새로 나온 ( 사실 이것도 나온지 10년 넘음 ) 엄격 모드에선 결과가 달라진단 말이지. 

 

 


 

엄격모드 

 

자바스크립트는 꽤 오랫동안 호환성 이슈 없이 발전했다. 기존의 기능을 변경하지 않으면서, 새로운 기능들이 추가되는 방식으로 말이다.

이는 기존에 작성한 코드는 절대 망가지지 않는다는 장점이 있었다. 하지만 자바스크립트 창시자들이 초기에 했던 실수나 불완전함 또한 영원히 박제 된다는 단점이 생겼다.

이는 ES5 가 등장하기 전까지는 계속 되었다. 하지만 ES5 이후, 새로운 기능들이 추가 되고 기존 기능 중 일부가 변경 되었다. 기존 기능을 변경했기 때문에, 하위 호환성 문제가 생겼다. 

그래서 변경 사항 대부분은 기본 모드에선 활성화 되지 않도록 설계되었다. 대신 use strict 라는 특별한 지시자를 사용해 엄격 모드를 활성화 했을 때만 변경 사항이 활성화 되게 해놓았다.

 

 

엄격 모드는 최상단에 위치하여야 한다.

그렇지 않으면, 엄격 모드가 활성화 되지 않을 수도 있다. 

그러니 주석을 제외하고 모든 코드의 최상단에다가 "use strict" 잊지 말자.

 

 

브라우저의 콘솔에다가도 엄격 모드를 적용하고 싶을 때는 최상단에 "use strict" 잊지 말기!

 

엄격 모드는 자바스크립트를 모던한 방식으로 작동하기 위한 방법이다.

 

하지만 꼭 "use stict" 의 명령어로만 작동시키지 않아도. 모던 자바스크립트에서는 '클래스' 와 '모듈' 이라 불리는 방식으로 자동으로 적용할 수 있다. 하지만 아직 이는 아직 나도 학습하지 않아서 뒤에서 클래스와 모듈에 대해서 정리할 때 다시 다루도록 하고,

 


 

지금은 다시 함수로 돌아와서, 최상단에서 "use strict" 를 적용시킨 상태에서 다시 시작하도록 하지!

 

 

 

 

쨋든 엄격모드를 활성화 시키면, 블록단위로 선언한 함수는 지역 스코프가 된다.

 

 

let age = prompt("당신의 나이는?", 20);

// 조건에 따라 함수를 선언함
if (age < 20) {

  function welcome() {
    alert("안녕!");
  }

} else {

  function welcome() {
    alert("안녕하세요!");
  }

}

// 함수를 나중에 호출.
welcome(); 

 

일단 먼저 조건에 따라 실행 시키는 함수를 만들고 실행시켜보자. 

 

 

 

 

잘 실행이 되는군 그런데 엄격 모드를 활성화해서 자바스크립트를 모던하게 바꿔보자.

 

 

//스크립트 최상단

"use strict";


//----중간에 코드가 있다고 가정 ----

let age = prompt("당신의 나이는?", 20);

// 조건에 따라 함수를 선언함
if (age < 20) {

  function welcome() {
    alert("안녕!");
  }

} else {

  function welcome() {
    alert("안녕하세요!");
  }

}

// 함수를 나중에 호출.
welcome(); 

 

 

 

 

 

이렇게 에러가 뜨게 된다. 함수가 엄격모드가 활성화 되면서 지역 스코프로 바뀌었기 때문. 그렇기 때문에 해당 함수의 블록 범위 안에서는 사용이 가능하지만, 함수 바깥에서 쓰게 된다면 이렇게 에러가 뜨게 된다!

 

'use strict';


let age = prompt('당신의 나이는?',20)

if (age < 20) {
             
  welcome();    //작동
  
  
  function welcome() {    
   
    alert("안녕!");          
  }  
  
  welcome();    //작동                       
                          
} else {
  
  welcome();   //작동
  
  function welcome() {
    
    alert("안녕하세요!");
  }
  
  welcome();   //작동   
  
}

welcome();  //Uncaught ReferenceError: welcome is not defined

 

 

여기서 블록 단위란 중괄호 ( {} )를 한 블럭이라고 치기 때문에, 함수가 선언된 블록 안에서는 모두 작동하지만, 함수 밖에서 호출된 맨 밑 welcome 은 작동하지 않는다. 

 

여기서는 함수를 각각 2번 작동 시키고, 마지막 welcome 은 에러가 뜨는 것.

 

 

물론,

let age = prompt('당신의 나이는?',20)

if (age < 20) {
             
       
  function welcome() {    
   
    alert("안녕!");          
  }  
  welcome();                           
                          
} else {
  
  function welcome() {
    
    alert("안녕하세요!");
  }
  welcome();   
  
}

 

 

 

 

물론 이렇게 함수를 쓰면, 해당 조건에 맞는 함수만 실행이 된다. 하지만 우리는 함수를 외부에서 불러와야 할 경우가 있을 수 있다.

 

 

그러니 이 때, 바로 함수 표현식이 쓰인다. 

 

'use strict';


let age = prompt("당신의 나이는 ? ", 20);

let welcome;        // welcome 선언.               

if (age < 20) {
   //welcome에 함수 표현식으로 할당.
   welcome = function() {
    alert("안녕!");
  };

} else {
  //welcome에 함수 표현식으로 할당.
  welcome = function() {
    alert("안녕하세요!");
  };

}

welcome();   //welcome 은 if 밖에서 선언되었기 때문에 호출 가능.

 

 

이렇게 if 밖에서 선언한 welcome 에 함수를 할당함으로써 if 문 외부에도 함수를 쓸 수가 있음.

이 경우는 좀 더 덜 헷갈리고, 외부에서도 함수를 부를 수 있다. 

 

이와 같이 조건문에서의 함수 사용이나, 외부에서 함수를 불러야 하는 경우는 함수 표현식을 쓰면 된다.

 

 

 

이렇게 함수도 값이기 때문에서 이렇게 쭈욱쭈욱 왔다면,

 


 

마찬가지로 함수는 값이기 때문에 함수 안에 인자 ( parameter ) 로 쓸 수 있고 필요하다면, 인자로 쓴 함수를 나중에 호출 할 수 있음.

>> 콜백 함수의 기본 개념

 

 

 

function ask(question,yes,no){

    if (confirm(question)) {
        //confrim 창의 확인을 눌렀을 때 해당 함수 실행.
        yes();

    }else{
        // 취소 눌렀을 때 해당 함수 실행.
        no();
    }
}


//확인을 눌렀을 때 사용할 확인 콜백 함수.

function showOK(){
    alert('확인');
}

//취소를 눌렀을 때 사용할 취소 콜백 함수.

function showCancel(){
    alert('취소');
}


//여기서도 마찬가지로 함수 자체를 인자로 갖기 때문에, 이름만 써줌. 그리고 위에서 yes(),no() 로 실행 시켜줌.

ask('확인?',showOK,showCancel)

 

이렇게 자바스크립트를 쓰다보면 , 콜백을 자연스레 마주치게 될 것이다. 이는 자바스크립트의 비동기화의 특성에서 비롯된 것인데, 요곳은 또 다음에 내가..정확하게 공부해서 오겠음 ㅎㅁㅎ

 

쨋든 여기서 showOK와 showCancel 은 콜백함수 또는 콜백이라 부른다. 핵심은 나중에 호출 한다는 것이고 , 위 예에서는 조건에 따라 각각 실행되는 콜백 함수가 각각 나뉜다.

 

지금은 콜백에 대해서 나중에 호출한다는 개념 정도만 알고 있기!

 

 

코드를 좀 더 짧게 적어보면,

 

//익명함수는 마찬가지로 변수에 할당한 것이 아니므로, 지역스코프가 되어 ask 함수 바깥에서 접근할 수 없음.

function ask(question, yes, no) {
    if (confirm(question)) yes()
    else no();
  }
  
  ask(
    "확인?",
    function() { alert("확인"); },
    function() { alert("취소"); }
  );

 

 

이렇게 변수에 할당하지 않고, 직접 인자에 함수로 써줄 수도 있는데, 이는 아까와 같이 지역 스코프가 되어 ask 함수 밖에선 접근할 수 없다.

여기서는 이름이 없는 함수. 즉 익명함수를 설명하기 위해, 또한 이렇게 줄여도 상관 없는 코드라 적어보았다!

 

 

 


후.. 오늘도 역시 길게 쓴 것 같닼ㅋㅋㅋㅋㅋㅋ 뭔가 혼자서 정리하려고 하는데, 역시 포스팅할 때마다 모르는 거 하나하나 쳐보면서, 또 다른 개념들을 보면서 정리하다 보면 금방이다 금방.. 오늘은 간만에 12시 넘어서 1시가 조금 안되는 초새벽..? (내기준) 에 오랜만에 포스팅이라 기분이 좋군 ㅎㅁㅎ 이제 시간도 많이 남는데 또 야행성 발동해서 자주 와야지 ( 제발 다짐만 하지말고 제발.. ) 

쨋든 오늘 포스팅 끝끄트트특!!!

 

 

 

댓글