함수란?
함수는 입력을 받아 출력을 내보내는 일련의 과정을 의미합니다.
즉 일정한 로직을 코드로 구현하고, 코드상에서는 블록으로 닫아 실행단위로 구분한 것을 말합니다.
함수으 구성요소는 다음과 같습니다.
function add (x, y) {
return x+y;
}
add(2, 5);
add는 함수의이름을 뜻하고,
x와 y는 매개변수를 의미합니다.
그리고 함수가 실행되고 return 키워드를 통해 값을 반환하게 되지요.
함수를 실행할 때 들어가는 2, 5를 인수라고 합니다.
함수를 사용하는 이유
함수는 실행단위로 묶은 코드 블록입니다.
따라서 언제든 원하는 기능을 정의하고 그대로 인수만 바꿔 적용하면
보다 코드를 간결하게 유지할 수 있습니다.
재사용성이 좋다고 할 수 있겠네요.
함수 리터럴
함수도 역시 객체 타입의 값입니다.
따라서 함수도 역시 함수 리터럴로 생성할 수가 있습니다.
함수 리터럴은 function키워드, 함수이름, 매개변수 목록, 함수 몸체로 구성됩니다.
함수이름 | -함수 이름은 식별자 입니다. 따라서 식별자 네이밍 규칙을 준수해야 합니다. -함수 이름은 함수 몸체 내에서만 참조할 수 있는 식별자입니다. -함수 이름은 생략할 수 있습니다. 이름 있는 함수는 기명함수, 없는 함수는 익명함수라고 합니다. |
매개변수 목록 | -0개 이상의 매개변수를 소괄호로 감싸고 쉼표롤 구분합니다. -각 매개변수에는 함수를 호출할 때 지정된 순서대로 할당됩니다. -매개변수는 함수 몸체 내에 변수와 동일하게 취급됩니다. 따라서 식별자 네이밍 규칙을 준수해야 합니다. |
함수 몸체 | -함수가 호출되었을 때, 일괄적으로 실행될 문들을 하나의 실행단위로 묶은 코드 블록입니다. -함수 몸체는 함수 호출에 의해 실행됩니다. |
함수 정의
함수 정의는 함수 호출 이전에 함수가 기능할 내용을 지정하는 것입니다.
//함수 선언문
function add (x,y) {
return x+y;
}
//함수 표현식
const minus = function (x,y) {
return x-y;
}
//function 생성자 함수
const times = new Function('x','y', 'return x*y');
//화살표 함수
const divide = (x,y) => x/y;
함수 리터럴과는 달리 함수 선언문은 함수 이름을 생략할 수 없습니다.
함수 선언문은 표현식이 아닌 문입니다.
자바스크립트 엔진은 생성된 함수를 호출하기 위해 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고, 거기에 함수 객체를 할당합니다.
//함수 리터럴
var foo = function add(x,y) {
return x+y;
}
console.log(foo(1,2)); // 3
//함수 선언문
function minus(x,y) {
return x-y;
}
minus(4,3); // 1
여기서 add 는 식별자이며, 함수 의 이름은 단지 함수의 이름일 뿐 함수 몸체 내에서만 참조할 수 있습니다.
만약 함수에 마땅한 식별자가 없다면 함수이름을 암묵적을 식별자로 할당할 뿐 함수이름과 식별자는 별개라는 것을 알아야 합니다.
함수는 객체 타입의 값이기 때문에 값처럼 변수에 할당을 할 수가 있습니다.
이런 성질을 가진 객체를 일급객체라고 합니다.
리터럴 형식으로 함수를 정의해서 사용하는 것을 함수 표현식이라고 합니다.
이제 함수의 식별자와 이름간의 관계가 조금은 이해 되기 시작할 것입니다.
식별자는 메모리에서 객체값을 불러오는 변수 명이고,
이 식별자에는 객체값이 저장되어있는 메모리 주소가 연결됩니다.
그리고 당연히 메모리에는 함수와 함수이름이 저장되어 있게 됩니다.
따라서 식별자가 따로 없는 선언문에서 식별자에 함수 이름이 암묵적으로 할당되고,
표현식에서는 함수 이름이 있든 없든 식별자만 사용되기 때문에 생략이 가능한 것입니다.
생성자를 이용해 함수를 만드는 것은 선언문이나 표현식과는 다르게 작동합니다.
이후에 배울 클로저가 동작하지 않습니다.
화살표함수는 항상 익명 함수로 정의을 하게 됩니다.
이름이 없는 익명함수로,
매개변수를 괄호롤 감싸고 화살표 를 붙여 함수의 몸체 부분을 작성하면 됩니다.
당연히 함수 이름이 없기 때문에 식별자가 있어야 하겠죠?
함수 호출
함수를 호출한다. = 함수를 사용한다
로 생각해도 무방할 것 같습니다.
인수로 받은 값을 매개변수에 대입하여 함수를 동작시킬 수가 있습니다.
다만 매개변수는 순서대로 지정이 되고 인수가 매개변수보다 부족해도 남은 변수에 값이 채워지지는 않습니다.
그리고 매개변수가 인수보다 적더라도 매개변수가 늘어나지도 않고 딱 매개변수만큼만 값을 받습니다.
그리고 이제 매개변수를 받았다면,
return 키워드를 통해 함수 코드블록을 탈출하고 값을 반환할 수 있습니다.
참조에 의한 전달과 외부 상태의 변경
function change(primitive, object) {
primitive += 10;
object.name='ye';
}
var num = 20;
var person = {name:'park'};
change(num, person);
console.log( num, person); // 20 {name:'ye'}
이렇게 함수에서 값을 변경하려고 시도했을 때,
원시값은 변하지 않지만 객체값을 변하게 됩니다.
외부에서 전역스코프에서 선언된 객체는 함수 내부에서 객체 값에 접근하여 변경하면 값이 변경됩니다.
왜냐하면 원시값은 메모리주소를 같이 참조하지 않고 새로운 메모리를 확보하는 반면
객체를 참조할 때는 그대로 같은 메모리 주소를 참조하기 때문입니다.
따라서 한 곳에서 객체 값을 변경한다면 그 객체를 참조하는 모든 곳에서 역시 객체의 값이 달라졌음을 알 수 있습니다.
다양한 함수의 형태
- 즉시실행함수
함수 정의와 동시에 즉시 실행되는 함수를 즉시 실행 함수라고 합니다.
즉시 실행 함수는 단 한 번만 호출되면 다시 호출할 수 없습니다.
(function() {
var a = 3;
var b = 2;
return a+b;
}());
이렇듯 익명함수로 사용할 수 있고, 만약 기명함수로 사용하게 된다면,
함수 몸체 안에서만 사용할 수 있습니다.
- 재귀함수
이름에서처럼 계속해서 자기 자신을 호출하는 함수입니다.
함수이름은 함수 몸체에서 사용할 수 있다고 했는데요.
재귀함수에서 사용할 수 있습니다.
다만 주의할 점은 탈출 조건을 잘 설정해줘야 합니다.
만약 그렇지 못하면 메모리가 넘칠 때까지 계속 함수를 호출하게 됩니다.
function countdown(n) {
if (n>0) {
console.log(n-1);
countdown(n-1);
}
}
- 중첩함수
함수 내부에 정의된 함수를 중첩함수라고 합니다.
그리고 중첩함수를 감싸는 함수를 외부함수라고 합니다.
- 콜백함수
만약 매개변수처럼 반복 사용되는 함수가 있다고 할 때, 우리는 함수도 매개변수에 전달해줄 수 있습니다.
이를 콜백함수라고 하고, 매개변수로 받는 함수를 고차함수라고 합니다.
- 순수함수,비순수 함수
순수함수는 어떤 외부 상태에도 의존하지 않고 오직 매개변수를 통해 함수 내부로 전달되는 인수에게만 의존해 값을 생성해 반환합니다. 함수의 외부상태에 의존하는 함수는 외부 상태에 따라 반환값이 달라지게 됩니다.
var count = 0;
function increase(n) {
return ++n;
}
count = increase(count);
console.log(count); // 1
count = increase(count);
console.log(count); // 2
비순수 함수는 외부상태에 의존하게 되어 반환값이 달라질 수 있고, 외부 상태도 변경할 수 있는 함수 입니다.
var count = 0;
function increase() {
return ++count;
}
increase();
console.log(count); // 1
increase();
console.log(count); // 2
얼핏 보면 두 함수 모두 같은 값들을 출력해서 비슷해 보이지만, 인수에 어떤 값들을 전달하는지를 보면 알 수 있습니다.
순수 함수는 인수에 전달되는 값에 따라 반환값이 달라지고,
비순수 함수는 인수에 어떤 값을 전달 하든 count변수를 증가시키는 기능만을 합니다.
즉 외부의 값에 따라 반환값이 달라진다는 것입니다.
count의 값이 4로 변경되었다고 했을 때,
두 함수에 num =100을 인수로 주었을 때,
순수함수에는 101이 반환될 것이고,
비순수함수는 count를 5로 증가시키기만 할 것입니다.
차이에 대해서 어느정도 감이 왔을거라 생각이 듭니다.
함수가 외부 상태를 변경하면 상태 변화를 추적하기 어려워 지기 때문에 함수 외부 상태 변경을 지양하는 순수 함수를 사용하는 것이 좋습니다.
'💪JavaScript > script.js' 카테고리의 다른 글
[모던 자바스크립트 딥다이브]_전역 변수의 문제점 어디까지 보고 오셨어요? (0) | 2023.08.20 |
---|---|
[모던 자바스크립트 딥다이브]_스코프 어디까지 보고 오셨어요? (0) | 2023.08.20 |
[모던 자바스크립트 딥다이브]_원시 값과 객체의 비교 어디까지 보고 오셨어요? (0) | 2023.08.20 |
[모던 자바스크립트 딥다이브]_객체 리터럴 어디까지 보고 오셨어요? (0) | 2023.08.20 |
[모던 자바스크립트 딥다이브]_타입 변환과 단축 평가 어디까지 보고 오셨어요? (0) | 2023.08.05 |