· 어떤 작업을 수행하기 위해 필요한 문(statement) 들의 집합을 정의한 코드블록
· 이름과 parameter(매개변수)를 가지며 필요시 호출하여 코드블록에 담긴 문들을 일괄적으로 실행 가능
객체 타입 => 이름(식별자) 함수 객체 주소
function test(a,b) {
return a + b
}
// call-by-value
test(2,3); // result = 5
// call-by-reference
let num2 = 2
let num3 = 3
test(num2, num3); // result = 5
매개변수 =
a, b
· 함수의 작업 실행을 위해 추가적인 정보 필요 시 parameter 지정
👉 Parameter 는 함수 내에서 variable 과 동일하게 동작
👉 Parameter 는 함수 정의된 내용과 동일한 형식으로 호출하여야 함
전달인자 =
2, 3
andnum2, num3
반환 값 =
a + b
· return 키워드는 함수를 호출한 코드에게 값 반환 시 사용
👉 Array 등을 이용하여 한 번에 여러 개의 값 리턴 가능
👉 Return 생략 가능 ( undefined 반환 )
👉 함수에서 return 키워드를 만나면 함수 실행 중단 후 함수를 호출한 코드로 되돌아감 ( return 이후의 구문은 실행되지 않음 )
JS 에서 function 은 일급 객체
일급 객체란, 다른 variable(변수) 처럼 대상을 다룰 수 있는 것
즉, JS에서 function 은 variable 처럼 다룰 수 있음
· First-class Object 란 생성, 대입, 연산, 인자 또는 반환값으로서의 전달 등 프로그래밍 언어의 기본적 조작을 제한없이 사용할 수 있는 대상
· function 과 다른 Object 를 구분짓는 가장 큰 특성은 호출이 가능하다는 점
⚪ First-class Object 의 특성
// 무명의 리터럴로 표현, 변수나 자료 구조에 저장
var increase = function(num) {
return ++num; };
var decrease = function(num) {
return --num; };
var cal = { increase, decrease };
// 함수의 매개변수에 전달, 반환값으로 사용
function makeCounter(predicate) {
var num =0;
return function() {
num = predicate(num);
return num; };
}
>> var increaser = makeCounter(cal.increase);
>> var decreaser = makeCounter(cal.decrease);
console.log(increaser()); // 1
console.log(increaser()); // 2
console.log(decreaser()); // -1
console.log(decreaser()); // -2
· 함수로서 선언을 하는 방법
· 함수명 생략 불가
· "Hoisting(호이스팅)" 에 의해 맨 위로 올려짐
· 함수 선언문의 시작은 function
function variable(parameter) { // code; [, return] }
// case 1
function square(num) {
return num * num;
}
square(2); // result = 4
// case 2
let square();
function square(num) {
return num * num;
}
square(2); // result = 4
⚪ 함수명 // square
· 함수 선언문은 함수명 생략 불가
· 재귀적 호출 또는 디버거로 구별 가능한 식별자
⚪ 매개 변수 // (num)
· 0개 이상의 목록으로 괄호로 감싸고 콤마로 분리
· Parameter 타입을 기술하지 않음
⚪ 함수 몸체 // { return num * num; }
· 함수가 호출되었을 때 실행되는 문들의 집합
· 중괄호( { } ) 로 문들을 감싸고 return 으로 결과값 반환 가능
· 함수의 일급객체 특성을 이용하여 함수를 정의하고 별도의 변수에 할당
👉 즉, 함수명이 아니라 할당된 함수를 가리키는 참조값을 저장 (객체의 특성, Pass-by-reference)
· "Hoisting(호이스팅)"이 일어나지 않음
· 익명함수 : 함수명 생략 가능
표현문은 "클로저(closure), 콜백(callback)" 등에 사용 가능
// 함수 표현식 ( 그리고 익명 함수 )
var foo = function(a, b) {
return a * b
};
// 기명 함수 표현식 (named function expression)
var foo2 = function multiply(a, b) {
return a * b;
};
// pass-by-reference
var foo3 = foo2
// result
>> console.log(foo2(5, 10)) // 50
>> console.log(multifly(5, 10) // ReferenceError (변수명으로 호출했을 때)
>> console.log(foo3(5,10)) // 50
-----
// 익명 함수 표현식 (anonymous function expression)
var bar = function(a, b) {
return a * b;
변수(함수)가 선언된 시점보다 앞에서 사용되는 것처럼 보이는 현상
· 함수 선언문 방식"만" 호이스팅이 발생
👉 자세한 내용
· 함수의 "정의" 와 "호출" 이 동시에 이루어짐
· 최초 한 번만 호출되며, 다시 호출할 수 없음
👉 1회 실행만 필요한 초기화 처리 등에 사용
· JS는 파일이 분리되어 있어도 Global Scope 는 하나라 그 안에 선언된 variable 또는 function 은 코드 내 어디서든 접근 가능
👉 즉시 실행 함수를 통해 혹시 모를 variable or function 중복에 의한 충돌을 방지
// 기명 즉시 실행 함수 (named immadiately-invoked function expresstion()
(function myFunction() {
var a= 3;
var b = 5;
return a * b
}());
// 익명 즉시 실행 함수
(function () {
var a= 3;
var b = 5;
return a * b
}());
<< 함수 선언문은 JS 엔진에 의해 함수 몸체를 닫는 중괄호 뒤에 ; 가 자동 추가됨 >>
function() {
code
}(); // => {};();
<< 따라서 즉시 실행 함수는 소괄호로 감싸줌 >>
// case1
(function() {
code
}());
// case2
(function() {
code
})();
· 함수 내부에 정의된 함수
· 내부 함수는 부모함수의 외부에서 접근 불가
/* parent 함수 내부에서 <child 내부함수의 variable> 은 참조 불가 */
function parent(param) {
var parentVar = param;
function child() {
var childVar = "Lee";
console.log(parentVar + ' ' + childVar); // Hello Lee
}
child();
console.log(parentVar + ' ' + childVar); // Reference Error
}
>> parent(hello);
-----
/* <함수 내부에 선언한 varable 로 선언된 함수> 는 외부에서 참조 불가 */
function sayHello(name) {
var text = 'Hello' + name;
var logHello = function() { console.log(text); }
logHello();
}
>> sayHello('Lee') // say Hello
>> logHello('Kim') // Reference Error
· 자기 자신을 호출하는 함수
· 자신을 무한히 연쇄 호출하기 때문에 탈출 조건이 반드시 필요
👉 탈출 조건이 없는 경우, stackoverflow 발생
// 피보나치 수열
function fibonacci(n) {
if (n < 2) return n;
return fibonacci(n -1) + fibonacci(n - 2);
}
>> console.log(fibonacci(4)) // 3
>> console.log(fibonacci(5)) // 5
>> console.log(fibonacci(6)) // 8
// 팩토리얼
function factorial(n) {
if (n < 2) return n;
return factorial(n -1) * n;
}
>> console.log(factorial(4)) // 24
>> console.log(factorial(5)) // 120
>> console.log(factorial(6)) // 720
· callback function 은 비동기 처리 모델에서 호출될 function 을 미리 전달하고, 처리 종료 후 callback 함수가 호출되도록 함
· Function 을 명시적으로 호출하는 방식이 아니라 "특정 이벤트 발생 시" 시스템에 의해 호출되어 동작
<html>
<body>
<button id="myBtn">Click me<button>
<script>
var button = document.querySelector('#myBtn');
button.addEventListener('click', function() {
console.log('button clicked');
});
</script>
</html>
· callback function 은 parameter 를 통해 전달되고, 전달받은 function 내부에서 "특정 시점"에 실행
👉 setTimeout()
을 통해 "특정시점"을 세팅하여 세팅된 시간이 경과하면 function 내부에 정의된 코드가 동작
setTimeout(function () {
console.log('1초 후 출력');
}, 1000);
· function 키워드 대신 화살표( => ) 를 사용하여 보다 간략한 방법으로 함수를 선언
👉 object 반환 시 소괄호( ( ) ) 이용
👉 return
키워드 생략 가능
⚪ 특징
· Hoisting 발생 X
· 호출한 object 가 아닌, 부모(상위 스코프)의 this를 가리킴 ( lexcial Scop )
· property 가 없어 생성자로 사용 불가
var pow = function(x) {
return x * x };
=
const pow = x => x * x;
<< parameter 지정 방법 >>
1. () => { ... } // 매개변수가 없는 경우
2. x => { ... } // 매개변수가 한 개인 경우, 소괄호 생략 가능
3. (x, y) => { ... } // 매개변수가 여러 개인 경우, 소괄호 생략 불가
<< 함수 몸체 지정 방법 >>
x => { return x * x } // single line block
x => x * x // function 전체가 한 줄의 구문이라면 중괄호 생략 가능
() => { return { a: 1}; }
() => ({a: 1}) // 객체 반환시 소괄호 사용
() => { // multi line block
const x = 10;
return x * x;
};
· 일반 function 은 선언 시 this 에 바인딩할 object 가 function 호출 시 어떻게 호출되었는지에 따라 "동적"으로 결정
· arrow function 은 선언 시 this 에 바인딩할 object 가 "정적"으로 결정
window.x = 1;
const normal = function() { return this.x };
const arrow = () => this.x;
>> console.log(normal.call({x:10})); // 10
>> console.log(arrow.call({x:10})); // 1
화살표 함수 사용 불가능한 경우
⚪ method 를 화살표 함수로 정의하는 것은 지양
· this가 method 를 호출한 object 가 아닌 상위 스코프의 this를 가리킴
· call, apply, bind method 를 통해 this 가 변경되지 않음
⚪ 생성자를 만들면 안됨
· 화살표 함수는 prototype 가 없음