익명함수
Anonymous Function
이름이 없기 때문에 그 자체로는 호출되지 않고 사용되지 않는다. ➡️ 함수를 활용하려면 변수에 할당하여 사용해야 한다.
(이렇게 변수에 할당된 함수를함수 표현식
이라고 한다. )const fn1 = function () { console.log('This is an anonymous function.'); }; 익명함수를 변수 fn1에 할당하여 선언
일반함수
Named Function
함수에 이름을 지정하여 함수를 선언한다.
(이를함수 선언식
이라 한다.)
일반함수도 변수에 할당하여 사용할 수 있다.const fn2 = function fn3 () { console.log('일반함수 fn3을 변수 fn2에 할당 후 호출'); fn2();
❗변수에 할당했으므로
변수명으로 호출이 가능하다 ( 함수명 X )
위에서 호출 X ( ∵ 함수 표현식이므로 호이스팅 X )
object
로 간주function이라는 키워드로 선언하여 코드를 저장한다.
function ex () {
if ( 조건에 맞지 않는다면 ){
// 조건에 맞지 않는다면 빨리 함수를 종료하도록 early return!
return;
}
// 조건에 맞는다면 실행할 긴 로직들 작성 ···
}
함수 내의 함수
외부 함수 내에서 선언되었기 때문에, 외부 함수의 스코프에서만 접근할 수 있다.
let globalMessage = 'global hello'; // 전역변수
function printMessage() {
let message = 'Hello'; // 지역변수
console.log(message);
console.log(globalMessage);
// 자식함수
function printAnother() {
console.log(message); // 부모함수에서 정의된 변수에 접근 가능
let childMessage = 'hello';
}
// 자식함수 내부에 정의된 변수에 접근하려 하니 에러 발생
console.log(childMessage);
}
printMessage();
// printAnother(); // 에러 발생
함수명 혹은 참조변수
( )
;
➡️ 함수 실행
함수 호출시 인수를 삽입하여 호출할 수 있다.
premitive 타입은 메모리에 value가 그대로 저장되어 있기 때문에 value가 전달된다.
object는 메모리에 reference가 저장되어 있기 때문에 reference가 전달된다.
changeName은 전달된 object의 name을 영희로 바꾸는 함수이다.
즉 kid.name의 값을 영희로 바꾼다.
JavaScript 함수 정의 시 매개변수의 기본 값을 설정하는 기능.
이를 통해 함수가 호출될 때 특정 매개변수가 제공되지 않으면, 그 매개변수는 기본 값을 가지게 된다.
default parameter 사용 X
⬇️
default parameter 사용 O
⬇️
나머지 매개변수
나머지 매개변수 사용시, 함수가 정해지지 않은 수의 매개변수를 배열로 받을 수 있다.
함수의 마지막 매개변수 앞에 ...
를 붙이면 (사용자가 제공한) 모든 후속 매개변수를 표준 JavaScript 배열에 넣도록 지정한다. 마지막 매개변수만 나머지 매개변수로 설정할 수 있다.
function test (a, b, ...manyMoreArgs){
console.log(a);
console.log(manyMoreArgs);
}
test('blue', 'red', 'black', 'yellow', 'wihte');
test('apple', 'pear', 'pitch');
test('tomato', 'banana');
⬇️
첫 번째 인수는 a, 두 번째 인수는 b로 맵핑된다.
➡️ 매개변수를 두 개만 제공하면 manyMoreArgs는 빈 배열
파라미터
는 함수 정의 시에 사용되는 변수들을 나타내고,
인수
는 함수 호출 시에 파라미터에 전달되는 실제 값들을 나타낸다.
함수에 전달된 인수에 해당하는 Array 형태의 객체.
arguments 객체를 사용하여 함수 내에서 모든 인수를 참조할 수 있으며, 호출할 때 제공한 인수 각각에 대한 항목을 갖고 있다. 항목의 인덱스는 0부터 시작한다.
예시 1>
function func1(a, b, c){
console.log(arguments[0] + arguments[1]);
console.log(c);
}
func1(100, 7, 3);
예시 2>
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
➕
완전 기본적인 개념도 잘 모르는 상태에서 이러한 코드를 처음에 봤을 때
함수를 선언할 때 파라미터를 작성하지 않았는데 어떻게 인수를 받아서
함수를 호출할 수가 있는지 의아했다.
알고 보니 JS의 함수는 파라미터를 명시적으로 선언하지 않아도
내부에서 arguments 객체를 사용하여 인수를 받을 수 있고,
전달된 모든 인수들에 접근할 수 있다고 한다.
❔ RESTparameter 와 arguments 객체의 차이
- arguments 객체는 유사 배열이지 실제 배열이 아니다. 그러나 나머지 매개변수는 Array 인스턴스이므로 sort, map, forEach, pop 등의 메서드를 직접 적용할 수 있다.
- ...restParam은 후속 매개변수만 배열에 포함하므로 ...restParam 이전에 직접 정의한 매개변수는 포함하지 않는다. 그러나 arguments 객체는, ...restParam의 각 항목까지 더해 모든 매개변수를 포함한다.
다른 함수에 전달인자로 전달하는 함수
화살표 함수 표현은 전통적인 함수표현의 간편한 대안이다.
작성방식
( )
=>
{ }
소괄호 안에 parameter 작성하고 중괄호 안에 함수 내용 작성 🔽
🔹 parameter가 하나인 경우 ➡️ 괄호 생략 가능const fn1 = a => { return a; }
🔹 함수 내용이 한 줄인 경우 ➡️ 중괄호 생략 가능 &
return
키워드 생략 가능const fn1 = (a, b) => a + b; 위처럼만 작성해도 a + b가 리턴된다
this
const obj = {
value: 42,
getValue: function() {
console.log(this.value); // 일반 함수에서의 this 바인딩
},
getArrowValue: () => {
console.log(this.value); // 화살표 함수에서의 this 바인딩
}
};
obj.getValue();
obj.getArrowValue();
다른 함수 선언 방식에서는 함수를 호출하는 시점에 따라
this가 동적으로 결정된다.
하지만 화살표 함수에서는 그런 동적인 바인딩이 없고,
⚡(즉 화살표 함수는 자신만의 this가 없다)
lexical scope(상위 스코프)의 this가 사용된다.
즉 화살표 함수의 this의 동작은 화살표 함수가 정의된 시점에서 결정되며
후에 어떤 위치에서 어떤 방식으로 호출되더라도 이에 영향을 받지 않는다.
어떻게 보면 참 뚝심 있는 애 같다.
이러한 동작으로 인해 화살표 함수는 주로 콜백 함수나 다른 함수 내에서
this 바인딩 문제를 해결하는 데 유용하다.
➕
setTimeout과 같은 일부 브라우저 내장 함수들은 실행 컨텍스트(context) 내에서의 this 값을 웹 브라우저 환경에서 전역 객체에 해당하는 window 객체로 설정한다.
이러한 동작은 초기 JavaScript의 설계 원칙 중 하나이다.
화살표 함수를 이용하면 this가 Timer 객체를 가리키게 할 수 있다
arguments
const regularFunction = function() {
console.log(arguments); // 일반 함수에서의 arguments 바인딩
};
const arrowFunction = () => {
console.log(arguments);
// 화살표 함수에서의 arguments 바인딩 --> 오류 발생
};
regularFunction(1, 2, 3);
arrowFunction(1, 2, 3);
⬇️
이렇게 오류가 나기 때문에 화살표 함수 내에서 인수들을 다룰 때는
REST parameter를 사용하는 것이 대안이 될 수 있다.
⬇️
const arrowFunction = (...args) => {
console.log(args);
};
➡️ new와 함께 사용하면 오류 발생
Immediately Invoked Function Expression (즉시 호출 함수 표현)
: 정의되자마자 즉시 실행되는 함수
전역 스코프에 불필요한 변수를 추가해서 오염시키는 것을 방지할 수 있을 뿐 아니라 IIFE 내부안으로 다른 변수들이 접근하는 것을 막을 수 있는 방법이다.
작성 방식 🔽
(
function( ) { ··· })
➡️ 함수 표현식 전체를 괄호로 감싸고
(
)
;
➡️ 함수를 호출하는 형태
(function hello(){
console.log('IIFE');
})();
재귀 함수
함수는 자신을 호출할 수 있다.
콘솔에 10부터 1까지 출력해 보기
function recurFn(number){
console.log(number);
if(number <= 1) return; //함수 종료
return recurFn(number-1); // 재귀 호출
}
recurFn(10);
⬇️
🆙 10!를 구해서 출력해 보자
내가 쓴 코드 ⬇️
function factorial(number){
if(number <= 1) return;
return number * factorial(number-1);
}
console.log(factorial(10)); // NaN
NaN이 나오는 이유는 1 이하일 경우에 어떠한 값도 누적시키지 않고
undefined가 반환되기 때문이다
console.log(factorial(1)); // undefined
즉 factorial(10)을 호출하면 10*9* ··· *2*1이 아니라
10*9* ··· *2*undefined가 되어서 NaN이 반환된 것이다.
수정 ⬇️
function factorial(number){
if(number <= 1) return 1;
return number * factorial(number-1);
}
console.log(factorial(10));