함수 만드는 방법
1. 함수 선언
function 함수이름(파라미터){
동작;
return 리턴값;
}
2. 함수 선언을 변수에 할당(함수 표현식)
const printA = function () {
console.log(‘A’);
}
printA();
- 2번과 같이 함수를 변수에 담음으로 값처럼 표현하는 것을 함수표현식(Function Expression)이라고 부른다.
- 함수표현식은 함수를 값처럼 표현한 모든것을 일컫는데,
- 예를들면 아래와같이 addEventListener를 할 때에 두번째 파라미터 함수를 주는 경우도 함수를 값처럼 표현한 것이므로 함수표현식이다.
document.querySelector('#btn').addEventListener('click', function()
{
console.log('button click');
});
1번과 2번의 차이점
1. 함수의 유효시점의 차이
- 함수선언: 호이스팅이 되어서 함수의 선언보다 호출이 위에 있어도 정상동작한다.
- 함수표현식: 선언한 경우, 변수는 선언 이전에는 접근할 수 없기 때문에 호출을 먼저할 수 없다.
2. 스코프의 차이
- 함수선언: var 키워드와 마찬가지로 함수 스코프를 가진다.
- 함수표현식 : 선언된 변수의 스코프에 따라 스코프가 결정된다.
(var로 선언돼었다면 함수 스코프를 가지고, let / const로 선언돼었다면 블럭스코프를 가진다.
둘 중 어떤것을 사용하는 것이 좋은가?
- 둘중 어떤것을 사용해도 크게 문제되지는 않지만 둘 중 하나로 일관된 것이 좋겠다.
- 보통은 함수선언이 많이 사용된다.
이름이 있는 함수 표현식
const sayHi = function printHiInConsole() {
console.log('Hi');
};
console.log(sayHi.name); // printHiInConsole
printHiInConsole(); // ReferenceError
- Named Function Expression (기명 함수 표현식)
- 위와같이 이름을 붙여서 함수표현식으로 함수를 만들 수 있다.
- 하지만 외부에서는 접근이 불가능하다.
그럼에도 기명함수표현식이 필요한 이유는
let getZero = function(n) {
if (n === 0) {
console.log('zero');
} else {
getZero(n - 1);
}
};
getZero(5);
위의 예시가 있을 때, 현재는 문제가 발생하지 않지만 아래와 같은 경우 문제가 발생할 수 있다.
let getZero = function(n) {
if (n === 0) {
console.log('zero');
} else {
getZero(n - 1);
}
};
let myFunction = getZero;
getZero = null;
myFunction(5); // TypeError
myFunction이 실행되다가 중간에 getZero가 null로 바뀌었기때문에 이후 else문의 getZero를 실행하는 부분에서 에러가 발생한다.
따라서 재귀함수는 반드시 기명함수표현식을 사용하는 것이 좋다.
아래와같이 수정한다면 정상동작한다.
let getZero = function printZero(n) {
if (n === 0) {
console.log('zero');
} else {
printZero(n - 1);
}
};
let myFunction = getZero;
getZero = null;
myFunction(5); // 정상 동작
즉시 실행 함수(IIFE)
- Immediately Invoked Function Expression
아래는 즉시 실행함수를 익명함수로 작성한 것이다.
(function (v) {
console.log(v);
})('Hi');
아래와 같이 이름을 줘서 만들 수도 있지만, 외부에서는 재사용이 불가능하다.
(function logValue(v) {
console.log(v);
})('Hi');
logValue('Hello'); // ReferenceError
그래서 즉시실행함수는 보통 익명함수로 많이 만든다.(재귀함수인 경우 제외)
즉시 실행함수의 활용
- 선언과 동시에 실행되기 때문에, 프로그램의 초기화 기능에 많이 활용된다.
- 재사용이 필요 없는 일회성 동작을 구설할 때에도 활용한다.
- 함수의 return값을 바로 변수에 할당하고 싶을 때에도 활용한다.
const firstUser = 'Ann';
const secondUser = 'Kathy';
const numberingMessage = (function () {
const message = `첫번째 순서는 ${firstUser} 이고, 두번째 순서는 ${secondUser} 이다.`;
return `numbering message : ${message}`;
})();
값으로서 함수
아래의 함수는 함수표현식으로 작성된 함수이다.
const printA = function(){
console.log('A');
}
console.log(printA); // function
console.dir(printA); // printA객체
자바스크립트에서 함수는 객체타입의 값으로 평가된다.
함수는 변수에도, 객체의 값으로도, 배열의 값으로도, 함수의 파라미터로도 자리할 수 있다.
콜백함수
다른 함수의 파라미터에 전달된 함수 = CallBack Function이라고 부른다.
고차함수
리턴값이 함수인 함수를 고차함수라고 한다.
function getPrintA(){
return function() { console.log('A')}
}
위의 함수는 리턴을 함수로 하고 있으니 고차함수이다.
const printA = getPrintHi();
printA();
위와같이 변수에 담아서 사용해도 되지만, 어떤 경우에는
getPrintA()();
위와같이 소괄호를 두 번 사용해서 내부의 함수를 바로 실행하도록 할 수도 있다.
이렇게 함수가 값으로서 사용될 수 있는 것을 일급 함수(First Class Function)이라고 부른다.
자바스크립트는 일급함수를 가지는 프로그래밍 언어이다.
파라미터
function printValue(value){ // 파라미터
console.log(value);
}
printValue('Hi'); // 아규먼트
함수 선언시 받아오는 값을 파라미터, 함수 호출시 보내는 값을 아규먼트라고 한다.
함수 호출시 아무 값도 보내지 않는다면, undefined가 보내진다.
function printNum(x,y = x+1){
console.log(x, y);
}
printNum(2); // 2 3
위와같이 파라미터가 2개인데, 하나가 다른 하나를 참조시켜 기본값을 설정할 수도 있다.
기본 값은 아규먼트를 생략했거나, undefined를 보낸 경우에만 사용된다.(어차피 아규먼트를 생략하면 undefined가 넘어옴)
기본값을 설정하는 문법은 ES2015이후부터 가능하다.
아규먼트
Argument갯수에 따라 유연하게 동작하는 함수를 만드는 방법
함수에는 arguments라는 객체가 있다. 유사배열형태를 리턴한다.
function printArguments(a, b, c){
for(const arg of arguments){
console.log(arg);
}
}
위와같이 작성하면, 함수 호출시 아규먼트를 몇 개를 넣어도 넣은 갯수만큼 출력된다.
그리고 arguments는 이렇게 사용되어야하니까 함수명, 변수명 등으로의 사용을 피해야한다.
Rest Parameter
arguments객체의 아쉬움을 보완한 ES6+문법.
function printArguments(…args){
for(const arg of arguments){
console.log(arg);
}
}
일반 파라미터 앞에 '...' 을 붙이는 것이 문법이다.
...arg는 배열이기때문에 배열메서드를 사용할 수 있다.
arguments객체는 유사배열이어서 배열메서드 사용이 불가능했다.
function printArguments(first, second, …others){
for(const arg of orators){
console.log(arg);
}
}
위와 같이 코드를 작성하면 첫번째, 두번째를 제외한 나머지 아규먼트들만 출력할 수 있다.
남아있는 모든 아규먼트를 받는 것이기 때문에, 파라미터의 가장 마지막에 작성되어야한다.
arguments보다는 restParameter의 사용이 권장된다.
Arrow function
모든 arrow function은 익명이기 때문에, 변수에 할당하거나 다른 함수의 argument로 할당할 때에(=콜백함수)많이 사용된다.
const getTwice = (number) => {
return number * 2;
}
const getTwice = number => number * 2;
위에 작성된 getTwice함수는 완전히 일치한다. 아래와 같은 상황일 때 축약이 가능하다.
1. 파라미터가 1개이면 파라미터를 감싸는 소괄호를 생략 가능하고
(파라미터가 없거나, 2개 이상이면 소괄호를 꼭 써줘야한다. 파라미터가 1개여도 소괄호를 쓰라고 권장하는 곳도 있다.)
2. 함수가 리턴문 한 문장으로만 되어있다면 중괄호와 return키워드를 생략 가능하다.
(하지만 리턴값이 {name: 'Ann'}과 같이 객체를 바로 리턴해야한다면, 에러가 발생하는데 ({name: 'Ann'}) 이렇게 소괄호로 감싸면된다.
arrowfunction은 arguments객체가 없다.
그리고 arrow function의 내부에서 사용하는 this는 arrow function이 선언되기 직전의 this와 같다.
(따라서 객체 안의 함수는 arrow function이 아닌 일반 함수를 사용하는 것이 권장된다.
키워드 this
함수 외부 또는 객체의 값으로서의 함수가 아닌, 일반 함수의 내부에서 this를 콘솔에 찍어보면 window객체가 출력된다.
console.log(this); // window객체가 출력된다.
객체 안에 들어있는 함수에서 사용하면,
함수를 호출한 객체를 출력한다.
function getFullName(){
return `${this.first} ${this.last}`
}
const ann = {
first : 'Kim',
last : 'Ann',
getFullName : getFullName
}
const Kathy = {
first : 'cho',
last : 'kathy',
getFullName : getFullName
}
console.log(ann.getFullName()); // kim Ann
console.log(kathy.getFullName()); // cho kathy
getFullName함수에서의 this는 함수를 호출한 객체인 ann과 kathy가 된다.
'JavaScript' 카테고리의 다른 글
JavaScript - Spread (0) | 2023.10.11 |
---|---|
JavaScript - 문장과 표현식 (0) | 2023.10.11 |
JavaScript- 변수와 스코프 (0) | 2023.10.11 |
JavaScript - 데이터타입, 연산자 (1) | 2023.10.11 |
JavaScript - 모던 자바스크립트 정의 (1) | 2023.10.11 |