# 함수

자바스크립트의 함수 정의는 C 스타일의 함수 정의와 유사합니다. 반환 자료형이 없으며, function이라는 키워드를 사용합니다.

매개 변수가 기본자료형인 경우에는 값이 전달됩니다. 그러나, 매개 변수가 배열이나 객체인 경우에는 그 속성의 변화가 함수 외부에서도 유효합니다.

모든 자바스크립트 함수는 값을 반환합니다. return 문을 통해 명시적으로 값을 반환하지 않는 함수는 undefined를 반환합니다.

```javascript
function myFunction(param) {
    return param * 2;
}
```

## 함수 표현식

자바스크립트에서는 함수 또한 객체이기 때문에 다음과 같은 표현도 가능합니다.

```javascript
let myFunction = function (param) {
    return param * 2;
};
```

함수 표현식을 사용하면 함수를 동적으로 만들 수 있습니다.

```javascript
let myFunction;
if (a > 0) {
    myFunction = function (param) {
        return param * 2;
    };
} else {
    myFunction = function (param) {
        return param * 4;
    };
}
```

## 중첩된 함수

함수 안에서 또 다른 함수를 정의하는 것도 가능합니다. 내부 함수는 외부 함수 안에서만 접근할 수 있습니다. 내부 함수에서는 외부 함수의 변수와 매개 변수에 접근할 수 있습니다.

```javascript
function addSquare(a, b) {
    function square(x) {
        return x * x;
    }
    return square(a) + square(b);
}
console.log(addSquare(2, 3)); // 13
```

```javascript
function outside(x) {
    function inside(y) {
        return x + y;
    }
    return inside;
}

let fnInside = outside(3);
console.log(fnInside(5)); // 8

console.log(outside(3)(5)); // 8
```

위와 같이 난해한 문법도 가능합니다.

## 클로져

자바스크립트의 함수는 중첩될 수 있다는 위의 특징을 활용하면, 다음과 같은 코드도 만들어 집니다.

```javascript
let Person = function (name) {
    let age;

    return {
        getAge: function () {
            return age;
        },
        setAge: function (newAge) {
            age = newAge;
        },
        getName: function () {
            return name;
        },
        setName: function (newName) {
            name = newName;
        }
    }
};

let charlie = Person("charlie");
charlie.setAge(14);
charlie.setName("Charlie");

console.log(charlie.getName());
```

## 매개변수

함수에 전달되는 매개 변수는 매개 변수 이름을 직접 참조할 수도 있지만, ```arguments```를 통해서 배열과 같은 방식으로도 처리할 수 있습니다.

```javascript
function func1(param1, param2) {
    for (let i = 0; i < arguments.length; i++) {
        console.log(arguments[i]);
    }
}

func1("A", "B");
```

이러한 특징을 활용하면, 임의 길이 매개 변수를 처리할 수 있습니다.

```javascript
function add() { // 함수 정의 부분의 매개 변수 항복은 별 의미가 없어집니다.
    let sum = 0;
    for (let i of arguments) {
        sum += i;
    }
    return sum;
}

console.log(add(1, 2, 3, 4, 5));
```

### 매개 변수의 기본값

함수 호출시에 생략된 매개 변수는 기본값인 undefined를 갖습니다.

```javascript
function myFunction(a, b) {
    console.log("a = " + a);
    console.log("b = " + b);
}

myFunction(1);
/*
    a = 1
    b = undefined
*/
```

ECMAScript 2015에서는 매개 변수의 기본값을 지정할 수 있습니다.

```javascript
function myFunction(a, b = 3) {
    console.log("a = " + a);
    console.log("b = " + b);
}

myFunction(1); // 생략된 매개 변수 b는 기본값이 3이 됩니다.
```

### 나머지 매개 변수

ECMAScript 2015에서는 임의 길이 매개 변수 기능이 추가되었습니다. 매개 변수 이름 앞에 ```…```을 붙입니다.

```javascript
function sum(...args) {
    let sum = 0;
    args.forEach(function (val) {
        sum += val;
    });
    return sum;
}

console.log(sum(1, 2, 3, 4, 5));
```

## 화살표 함수

위의 코드는 다음과 같이 짧게 줄일 수 있습니다.

```javascript
function sum(...args) {
    let sum = 0;
    args.forEach((val) => sum += val);
    return sum;
}
```

## 미리 정의된 전역 함수

```javasc
eval()
```

문자열로 표현된 자바스크립트 코드를 실행합니다.

```javascript
inFinite()
```

매개 변수로 전달된 값이 유한한지 확인합니다.

```javascript
isNaN()
```

NaN인지 확인합니다. Number.isNan() 또는 typeof를 대신 사용하는 것이 좋습니다.

```javascript
parseFloat()
```

문자열을 실수로 바꿉니다.

```javascript
parseInt()
```

문자열을 정수로 바꿉니다.

```javascript
encodeURI()
encodeURIComponent()
decodeURI()
decodeURIComponent()
```

URI를 UTF-8 이스케잎 문자로 (또는 그 반대로) 변환합니다.

```javascript
let uri = "https://www.elex-project.com/test?a=몰라&b=알수가없어";
console.log(encodeURI(uri));
console.log(encodeURIComponent(uri));
/*
https://www.elex-project.com/test?a=%EB%AA%B0%EB%9D%BC&b=%EC%95%8C%EC%88%98%EA%B0%80%EC%97%86%EC%96%B4

https%3A%2F%2Fwww.elex-project.com%2Ftest%3Fa%3D%EB%AA%B0%EB%9D%BC%26b%3D%EC%95%8C%EC%88%98%EA%B0%80%EC%97%86%EC%96%B4
*/
```