자바스크립트는 함수를 특별한 종류의 값으로 취급합니다. 다른 언어에서처럼 "특별한 동작을 하는 구조"로 취급되지 않습니다.
함수 선언(Function Declaration)
function sayHi() {
alert( "Hello" );
}
함수 표현식(Function Expression)
// 함수는 `값`으로 취급 된다 (= 변수에 할당할 수 있다)
// 함수를 복사해서 다른 변수에 넣을 수 있다
// 끝에 세미콜론 (함수 선언문은 X)
let sayHi = function() {
alert( "Hello" );
};
// 자바스크립트는 괄호가 있어야만 함수가 호출
alert( sayHi );
function sayHi() { // (1) 함수 생성
alert( "Hello" );
}
let func = sayHi; // (2) 함수 복사
func(); // Hello // (3) 복사한 함수를 실행(정상적으로 실행됩니다)!
sayHi(); // Hello // 본래 함수도 정상적으로 실행됩니다.
본질은 값이기 때문에 값에 할 수 있는 일을 함수에도 할 수 있습니다.
변수를 복사해 다른 변수에 할당하는 것처럼 함수를 복사해 다른 변수에 할당할 수도 있습니다.
function ask(question, yes, no) {
if (confirm(question)) yes()
else no();
}
function showOk() {
alert( "동의하셨습니다." );
}
function showCancel() {
alert( "취소 버튼을 누르셨습니다." );
}
// 사용법: 함수 showOk와 showCancel가 ask 함수의 인수로 전달됨
ask("동의하십니까?", showOk, showCancel);
function ask(question, yes, no) {
if (confirm(question)) yes()
else no();
}
ask(
"동의하십니까?",
function() { alert("동의하셨습니다."); },
function() { alert("취소 버튼을 누르셨습니다."); }
);
// 함수 선언문
function sum(a, b) {
return a + b;
}
// 함수 표현식
let sum = function(a, b) {
return a + b;
};
함수 선언문은 함수 선언문이 정의되기 전에도 호출할 수 있습니다.
// 함수 선언문
sayHi("John"); // Hello, John
function sayHi(name) {
alert( `Hello, ${name}` );
}
// 함수 표현식
sayHi("John"); // error!
let sayHi = function(name) { // (*) 마술은 일어나지 않습니다.
alert( `Hello, ${name}` );
};
let age = prompt("나이를 알려주세요.", 18);
// 조건에 따라 함수를 선언함
if (age < 18) {
function welcome() {
alert("안녕!");
}
} else {
function welcome() {
alert("안녕하세요!");
}
}
// 함수를 나중에 호출합니다.
welcome(); // Error: welcome is not defined
let age = prompt("나이를 알려주세요.", 18);
let welcome;
if (age < 18) {
welcome = function() {
alert("안녕!");
};
} else {
welcome = function() {
alert("안녕하세요!");
};
}
welcome(); // 제대로 동작합니다.
let calculateTotal = function () {
// 함수 안에서만 접근이 가능한 인수들의 집합 객체로서 배열과 유사한 형태를 가지고 있는 것 : arguments
console.log(arguments);
};
const result = calculateTotal(1000, 500, 200, 6500, 100);
let calculateTotal = function () {
// 함수 안에서만 접근이 가능한 인수들의 집합 객체로서 배열과 유사한 형태를 가지고 있는 것 : arguments
// -----1번째 방법 for 문-----
let total = 0;
for (let i = 0; i < arguments.length; i++) {
total += arguments[i];
}
// -----2번째 방법 for...of 문-----
let total = 0;
for (const key of arguments) {
total += key;
}
// -----3번째 방법 forEach 빌려쓰기-----
let total = 0;
Array.prototype.forEach.call(arguments, function (item) {
total += item;
});
// -----4번째 방법 유사배열을 slice를 빌려 서서 배열로 만드는 방법-----
let total = 0;
let realArray = Array.prototype.slice.call(arguments);
realArray.forEach(function (item) {
total += item;
});
// -----5번째 Array.from() 메서드를 이용해 유사배열을 배열로 만드는 방법-----
// Object.prototype.toString() 인스턴스 메서드
// Object.entries() 스태틱 메서드
let total = 0;
let realArray = Array.from(arguments);
realArray.forEach(function (item) {
total += item;
});
// -----6번째 spread syntax-----
let total = [...arguments].reduce((a, b) => (a += b));
let total = 0;
let realArray = [...arguments];
realArray.forEach(function (item, index, array) {
total += item;
});
// -----7번째 배열 메서드 reduce() 이용하기-----
let realArray = [...arguments];
return realArray.reduce((acc, cur) => acc + cur, 0);
};
const result = calculateTotal(1000, 500, 200, 6500, 100);
console.log(result);
let anonymousFunctionExpression = function () {}; // 변수명이 함수명
console.log(anonymousFunctionExpression.name); // 함수도 객체다.
let namedFunctionExpression = function hello() {
};
호출할 때는 hello() 아니고 namedFunctionExpression()
let callbackFunctionExpression = function(callback) {
callback();
};
callbackFunctionExpression(
function () {
console.log('콜백 함수 실행');
}
)
(function(){
console.log('즉시 함수');
})()
함수 표현식보다 단순하고 간결한 문법으로 함수를 만들 수 있는 방법
// 일반 함수 표현식
let func = function(arg1, arg2, ...argN) {
return expression;
};
// 화살표 함수
let func = (arg1, arg2, ...argN) => expression
let sum = (a, b) => { // 중괄호는 본문 여러 줄로 구성되어 있음을 알려줍니다.
let result = a + b;
return result; // 중괄호를 사용했다면, return 지시자로 결괏값을 반환해주어야 합니다.
};
// () => {} 화살표 함수에는 argments 가 없다. 따라서 function(...){ argments }의 기능을 대신하는 (...rest) parameter를 사용해야 한다.
// 매개변수 밖에서 쓰면 기존의 spread syntax다.
let calcAllMoney = (a, b, ...args) => {
// let total = 0;
// args.forEach((item) => (total += item));
return args.reduce((acc, item) => acc + i
};
const result = calcAllMoney(1_000, 500, 200, 2_000);
console.log(result);
const result = calcAllMoney(1_000, 500, 200, 2_000);
일 때
let calcAllMoney = (...args) => {...}
여기서 ...args는 1000, 500, 200, 2000 모든 값이고
앞에 매개변수를 추가하게 된다면
let calcAllMoney = (a, b, ...args) => {...}
여기서 순차적으로 a가 1000, b가 500이 되면서 나머지 200과 2000이 ...args에 담기게 됩니다.
// 함수 선언문
function normalFunction() {}
// 함수 표현식
const expressionFunction = function () {};
// 화살표 함수식
const arrowFunction = () => {};
// normalFunction, expressionFunction는 컨스트럭터가 없다. 즉, 함수로써의 기능만 수행한다. 따라서 가볍다.
/* 컨스트럭터란?
function Button() {}
const a = Button(); // 리턴된 값이 a, 리턴값이 없다면 undefined
const b = new Button(); // new 키워드를 붙이면 b에는 객체가 담긴다.
new 기능을 컨스트럭터에서 지원한다.
즉, new 키워드를 붙여서 객체를 생성하는 생성자 함수가 되거나, 붙이지 않아 일반 함수가 되는데 이를 구분하기가 힘들기 때문에 arrowFunction에서는 컨스트럭터를 지원하지 않는다.
*/
// 함수 선언문
function normalFunction() {
console.log(this);
}
normalFunction();
// 함수 표현식
const expressionFunction = function () {
console.log(this);
};
expressionFunction();
// 화살표 함수식
const arrowFunction = () => {
console.log(this);
};
arrowFunction();