일련의 과정을 문으로 구현하고 코드 블록으로 감싸서 실행 단위로 정의한 것 -> 값임
=> 매개변수(내부로 입력을 전달받는 변수), 인수(입력), 반환값(출력)
함수 정의 -> 매개변수를 통해 인수를 함수에 전달하며 실행(=> 함수 호출) -> 반환값 반환
=> 가독성이 좋은 코드가 좋은 코드
함수 선언 방식은 아래 챕터 4가지
function add(x, y){
return x + y
}
자바스크립트의 함수는 값처럼 변수에 할당 할 수도 있고 프로퍼티 값이 될 수도 있으며 배열의 요소가 될 수도 있음, 값처럼 자유롭게 사용 가능 => 일급 객체
함수 표현식: 함수 리터럴로 생성한 함수 객쳬를 변수에 할당
익명 함수: 함수 리터럴의 함수 이름은 생략한 것
함수 선언문과 함수 표현식은 유사한 동작으로 보이지만 정확히 동일하게 동작하지는 않음
var add = function foo(x, y) {
return (x + y)
}
console.log(add(2, 5))
console.log(foo(2, 5)) // foo is not defined
// 함수 참조
console.dir(add); // f add(x,y)
console.dir(sub); // undefined
// 함수 호출
console.log(add(2, 5)); // 7
console.log(sub(2, 5)); // TypeError: sub is not a function
// 함수 선언문
function add(x, y) {
return x + y
};
// 함수 표현식
var sub = function (x, y) {
return x - y
};
함수 선언문으로 정의한 함수는 함수 선언문 이전에 호출 가능 / 함수 표현식으로 정의한 함수는 함수 표현식 이전에 호출 불가능 => 두 함수의 생성 시점이 다르기 때문
함수 선언문으로 함수를 정의하면 런타임 이전에 함수 객체가 먼저 생성됨
자바스크립트 엔진은 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고, 생성된 함수 객체를 할당함
=> 런타임에는 이미 함수 객체가 생성되어 있고 함수 이름과 동일한 식별자에 할당까지 완료된 상태
=> 함수 선언문 이전에 함수를 참조할 수 있으며 호출도 가능
함수 호이스팅 / 변수 호이스팅
- 런타임 이전에 자바스크립트 엔진에 의해 먼저 실행되어 식별자를 생성한다는 점은 동일
- var 키워드로 선언된 변수는 undefined로 초기화 / 함수 선언문을 통해 암묵적으로 생성된 식별자는 함수 객체로 초기화
-> 함수 표현식으로 함수를 정의하면 함수 호이스팅이 발생하는 것이 아니라 변수 호이스팅이 발생(undefined)
-> 함수 표현식으로 정의한 함수는 반드시 함수 표현식 이후에 참조 또는 호출(아니면 타입에러 발생)
var add = new Function('x','y','return x + y');
console.log(2, 5)); //7
var add = (x, y) => x + y;
console.log(2, 5)); //7
function add(x, y){ // (x, y)는 매개수
console.log(arguments)
return x + y; // x + y는 반환값
}
let result = add(2, 5) // 2, 5는 인수
자바스크립트는 암묵적 타입 변환함 -> 함수를 정의할 때 적절한 인수가 전달되었는지 확인 필요
=> 부적절한 호출을 사전에 방지할 수는 없고 에러는 런타임에 발생
-> 타입스크립트 사용, 단축평가 사용, 매개변수 기본값 사용 등 방법 찾기
함수는 return 키워드와 표현식(반환값)으로 이뤄진 반환문을 사용해 실행 결과를 함수 외부로 반환 가능
함수 호출 표현식 -> 반환값으로 평가됨
반환문 역할
// 매개변수 primitive는 원시 값을 전달받고, 매개변수 obj는 객체를 전달 받음
// 매개변수 primitive은 재할당을 통해 할당된 원시 값을 새로운 원시 값으로 교체
// 객쳬 타입 인수를 전달받은 매개변수 obj는 재할당 없이 직접 할당된 객쳬를 변경
function changeVal(primitive, obj) {
primitive += 100;
obj.name = "Kim";
}
// 외부 상태
var num = 100;
var person = { name: "Lee" };
console.log(num); // 100
console.log(person); // { name: "Lee" }
changeVal(num, person)
console.log(num); // 100 -> 원본 훼손 안 됨(값 자체 복사)
console.log(person); // { name: "Kim" } // 원본 훼손됨(참조 값 복사)
(function () {
var a = 3;
var b = 5;
return a * b;
}());
외부 함수
라고 부름반복하는 일은 변하지 않고 공통적으로 수행하지만 반복하면서 하는 일의 내용은 다른 함수(일부분만 다를 때) => 함수의 변하지 않는 공통 로직은 미리 정의해 두고, 경우에 따라 변경되는 로직은 추상화해서 함수 외부에서 함수 내부로 전달해야함
콜백 함수: 함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수
고차 함수: 매개 변수를 통해 함수의 외부에서 콜백 함수를 전달받은 함수
콜백 함수도 고차 함수에 전달되어 헬퍼 함수의 역할 => 고차 함수는 콜백 함수를 자신의 일부분으로 합성
콜백 함수는 고차 함수에 의해 호출됨, 고차 함수는 필요에 따라 콜백 함수에 인수를 전달 가능
순수 함수 : 부수 효과가 없는 함수
-> 동일한 인수가 전달되면 언제나 동일한 값을 반환
-> 외부 상태에 의존하지 않고 오직 매개변수를 통해 함수 내부로 전달된 인수에게만 의존해 값을 생성해 반환
-> 순수 함수는 최소 하나 이상의 인수를 전달 받음(0개면 상수와 마찬가지)
-> 인수를 변경하지 않는 게 기본(인수의 불변성), 외부 상태도 변경하지 않음
비순수 함수 : 부수 효과가 있는 함수(외부 상태에 따라 반환값이 달라지는 함수)
-> 함수 내부에서 외부 상태를 직접 참조하지 않더라도 매개변수를 통해 객체를 전달받는 것도 포함
-> 비순수 함수를 최대한 줄이는 것은 부수 효과를 최대한 억제하는 것
var count = 0;
// 순수 함수 increase는 동일한 인수가 전달되면 언제나 동일한 값을 반환
function increase(n) {
return ++n;
}
count = increase(count);
console.log(count); // 1
// 비순수 함수
function increase_2() {
return ++count;
}
// 비순수 함수는 외부 상태를 변경해 상태 변화를 추적하기 어려움
increase_2();
console.log(count); // 2
=> 함수형 프로그래밍은 결국 순수 함수를 통해 부수 효과를 최대한 억제해 오류를 피하고 프로그램의 안정성을 높이려는 목적