본문 바로가기
작은 모듈(IT구슬)

자바스크립트 함수 유형

by IT여행자 2020. 6. 3.
728x90

안녕하세요. IT 이곳저곳을 여행하고 있는 IT여행자입니다. 이번 IT 작은 구슬에서는 자바스크립트에서 사용되는 함수를 정의하는 다양한 방법들에 대해서 설펴 보고자 합니다.

 

  1. 선언적 함수
  2. 함수 표현식
  3. 익명함수(즉시실행함수)
  4. 화살표 함수
  5. 생성자를 통한 함수
  6. 리터널 유형 함수

 

1. function 함수명( [매개변수] ) {... } 선언적 함수

가장 보편적으로 많이 사용하고 있던 함수 선언 형식입니다. 함수가 hoisting 된다는 특징이 있습니다. 함수가 hoisting 된다는 의미는 선언되는 순서와 상관없이 스크립트 엔진은 가장 먼저 메모리 스택에 함수를 로딩하여 사용할 준비를 해 준다는 의미입니다. 즉, 코드의 순서가 "사용->선언"순으로 작성하든, "선언->사용" 순으로 작성하든 상관이 없다는 말입니다. 이러한 특징은 사용상 대단한 편리성을 주지만, 선언된 모든 function들이 사용 유무에 상관없이 메모리에 상주하게 되기 때문에 메모리 압박을 받습니다.

 

hoisting의 간단한 사용예는 아래와 같을 것입니다.

var s = sum(10,20)
...
function sum(x,y){
    return x+y;
}

 

위와 같이 sum() 함수를 호출하여 사용하는 코드를 먼저 기술하고, sum() 함수가 정의되는 부분을 나중에 기술해도 프로그램 실행과는 상관이 없다는 의미입니다. 물론 프로그램의 분석하는 과정의 어려움이나 프로그램의 흐름상 지향하는 방법이지만 어떤 방법이든 단점만 존재하는 부분이 없기 때문에 프로그램의 흐름에 상관없이 사용해야 하거나, 독립적으로 반복적인 처리 과정이 있는 경우 종종 사용되는 방법입니다.

 

2. var func = function([매개변수]) {... } 함수 표현식

정의된 함수의 내용을 하나의 변수(객체)에 담아 사용하는 방법입니다. 함수 표현식이라고 알려져 있습니다. 함수 표현식은 보이는 모양 그대로 하나의 함수를 변수에 담아 사용하는데 이는, 변수가 선언되는 영역(scope)에서만 사용할 수 있듯이 함수도 선언된 지역(scope)내에서만 사용할 수 있다는 특징이 있습니다. 

이런 특징이 별거 아닌 것처럼 생각될 수도 있지만 프로젝트의 규모가 커지거나 복잡해지는 경우 다른 영역에서 선언된 함수와의 트러블 현상이 발생하지 않는다는 것이 대단한 장점으로 작용됩니다. 또한 해당 영역이 종료되면 메모리에서 제거되기 때문에 메모리 압박에서도 조금은 더 자유로울 수 있다는 특징이 있습니다.

그러나 함수가 hoisting이 되기 않기 때문에서 함수를 사용하기 전에 반드시 함수를 선언해야 한다는 특징이 있습니다.

console.log( sum(10,20) ); // 오류 발생
var sum = function(x,y){
    return x+y;
}

 

위의 코드가 정상적으로 실행되려면 함수의 호출 부분이 함수의 선언부 하단에 위치해 있어야 합니다.

var sum = function(x,y){
    return x+y;
}
console.log( sum(10,20) ); // 정상

 

함수 표현식으로는  var func = function MyName() {... }와 같이 function 뒤에 MyName처럼 함수명처럼 붙여 줄 수도 있지만 해당 MyName으로는 사용할 수 없습니다. 다만 해당 함수에서 오류가 발생한 경우 객체명 대신 어느 함수에서 오류가 발생했는지를 조금은 명확히 표시해 줄 수는 있습니다.

 

func1 = function(){...}와 같이 작성되었을 때와 func1 = function MyFunc(){... }와 같이 작성되었을 때 해당 함수에서 오류가 발생하면 오류가 발생된 위치를 조금 다르게 표시해 주는 에러 메시지 예입니다.

 

3. (function(){ ... })() 즉시 실행 함수

'익명함수' 또는 '즉시 실행 함수'라 표현합니다. 함수 및 변수 선언이 다른 스크립트에 영향을 주거나 받지 않습니다. 따라서 스크립트를 사용한 모듈을 개발하거나 공동작업 시 개개인의 스크립트를 독립적으로 작동해야 할 때 작성합니다. 가장 대표적인 예가 jQuery 라이브러리라 할 수 있습니다.

 

작성 형태는 아래의 몇 가지로 나누어 볼 수 있습니다.

 

[기본형태]

외부에서 전달되는 값 없이 즉시 실행되는 형태입니다.

( function(){
    console.log("즉시실행됨")
   }
)()

 

자바스크립트가 실행되는 순간 즉시 실행되어 콘솔창에 메시지가 출력됩니다.

 

[외부값을 전달받아 실행되는 형태]

즉시실행함수 외부에 있는 자원을 전달받아 실행하는 형태입니다.


    function(x){
        console.log(x) // 100
    }
)(100);

 

정수값 100이 함수의 매개변수 x에 전달된 후 즉시 실행됩니다. 숫자 이외에 객체를 전달하여 사용할 수도 있습니다.

var obj = { ... }

    function(x){
        console.log(x.PI) 
    }
)(obj);

 

독립적인 객체 obj를 인수값으로 전달하여 사용되는 예입니다. obj를 x로 전달받아 x안에 있는 요소들을 사용할 수 있습니다.

 

[즉시실행함수 내부함수를 외부에서 사용하는 형태]

즉시실행 함수내부에서 선언된 함수들을 즉시실행 함수 외부에서 사용할 수 있는 방법도 있습니다. 이는 즉시실행함수의 return문장을 사용하여 함수들을 리턴하여 사용합니다.

<script>
    const myFunc = (
        function(){
            function sum(x,y){
                return x+y;
            }
            function div(x,y){
                return x/y;
            }
            //내부 함수를 외부에서 사용할 수 있도록 조치
            return {
                sum, div
            }
        }
    )()

    console.log(myFunc.sum(10,20)) // 30
    console.log(myFunc.div(10,4)) // 2.5
</script>

즉시실행함수의 끝부분에 return문장에 의해 내부 함수인 sum과 div를 리턴하고 있습니다. 즉시실행함수가 익명함수라 불려지기는 하지만 함수 전체를 하나의 객체에 담을 수는 있습니다. 따라서 위의 코드를 보면 하나의 즉시실행함수를 myFunc에 담아 사용되는 것을 볼 수 있을 것입니다. 이렇게 생성된 객체인 myFunc를 통해 리턴된 sum과 div함수를 사용할 수 있습니다.

 

4. ()=>{ ... } 화살표 함수

'화살표 함수'라고 표현합니다. 문법을 굉장히 간결하게 사용할 수 있다는 특징이 있습니다. 단, 생성자 함수를 사용할 수 없고, arguments 객체를 지원하지 않아 매개변수들을 보다 다양한 형태로 처리해야 하는 경우에는 사용이 적절하지 않습니다.

많이 사용되는 몇 가지 기본 유형들을 나열해 보겠습니다.

const func=()=>{
    console.log("화살표 함수")
}
func()

const func2=(x)=>{
    console.log('x=',x)
}
func2(100)

const func3 =(x,y)=>{
    return (x>y)? x: y;
}
console.log(func3(10,200))

 

다음은 다른 고차원적인 함수들과 연합하여 사용하는 예를 들어 보도록 하겠습니다.

 

[filter함수 사용예]

filter함수와 화살표 함수를 사용하여 배열값에서 짝수들만 추려서 반환하는 예입니다.

const data = [1,2,3,4,5,6];
// 일반 함수
let r1 = data.filter( function(d){
    return d%2==0
} )
// 화살표 함수
let r2 = data.filter(d=> d%2===0)
console.log('짝수:', r1); // [2, 4, 6]
console.log('짝수:', r2); // [2, 4, 6]

 

filter함수는 data 배열에 있는 값들을 차례대로 d에 대입하고 조건에 맞으면 그 값을 리턴하여 새로운 배열 r1, r2를 만들어 출력하는 예입니다.

 

[map함수 사용예]

json 타입으로 저장된 데이터중에서 product속성의 데이터만 가져와 새로운 배열 products를 만들어 출력하는 예입니다.

const json = [
    { product : '사과', ea : 100},
    { product : '자두', ea : 200},
    { product : '딸기', ea : 300},
    { product : '수박', ea : 400},

];

// 일반함수
let products1 = json.map(function(d){
    return d.product
} )
// 화살표 함수
let products2 = json.map(d=> d.product)
console.log('상품:', products1); // ['사과', '자두', '딸기', '수박']
console.log('상품:', products2); // ['사과', '자두', '딸기', '수박']

 

화살표 함수 유형을 사용하면 대부분의 코드들이 생각 외로 간략해짐을 알 수 있겠습니다.

 

5. var myFunc = new Function() 생성자 함수

생성자 함수를 사용하여 함수를 정의하는 방법이 있습니다. 런타임시 동적으로 함수를 적용할 수 있다는 특징이 있지만 보안 문제나 성능 저하 잇슈들로 인해 일반적으로 사용하지는 않는 방법이기는 합니다. new Function()의 파라미터값 중에 항상 마지막 파라미터는 함수의 몸체(function body)를 의미합니다.

 

따라서, 기본 구조는 아래와 같습니다.

const func = new Function( 'param1', ... 'paramN', '함수 몸체' )

 

많이 사용되는 유형이 아니므로 간단한 예만 들어 보겠습니다.

const func = new Function('x', 'y' , 'return x+y')
console.log(func(10,20)) // 30

 

 

6. var func = {} 리터널 유형

'리터널 유형'으로 선언하여 사용하는 방법입니다. 이는 객체와 관련된 처리 내용들을 내부 함수와 변수를 선언하여 그룹화할 수 있다는 장점이 있습니다. 

  • 모든 요소들은 콤마로 연결된다.
  • 내부 변수들은 모두 key:value 형태로 선언된다.
  • 함수내부에서 자신의 요소를 접근하려고 할 때 'this'키워드를 붙여 주어야 한다.
  • 또 다른 객체로 생성할 수는 없다.

member 개체 안에 name, age 변수를 선언하고 이를 접근하여 사용하는 예입니다.

const member = {
    name : 'hong',
    age  : 20,
    getName(){ return this.name },
    getAge() { return this.age },
    setName(x){ this.name = x},
    setAge(x){ this.age = x}
}
        
console.log('name:', member.name) // name:hong
console.log('age:', member.age) // age:20

console.log('name:', member.getName()) // name:hong
console.log('age:', member.getAge()) // age:20

member.setName('park')
member.setAge(30)
console.log('name:', member.getName()) // name:park
console.log('age:', member.getAge()) // age:30

 

자바스크립트에 사용되는 모든 함수의 유형과 사용법을 다룬 것은 아니지만 다양한 형태의 함수 선언 방법을 익혀 둠으로써 필요에 따라, 개발 환경에 따라 선택하여 사용할 수 있을 것이라 생각됩니다.