1. 함수의 정의
- 정의 : 한번 정의하면 몇번이고 호출할 수 있는 자바스크립트 코드 블록
- 함수 구조
1) function 함수명 (매개변수) { 함수 실행 블록 }
2) 함수명 => (매개변수) { 함수 실행 블록}
// 0의 각 프로퍼티 이름과 값을 출력, undefined를 반환
function printprops(obj) {
for(let p in obj) {
console.log(`${p}: ${obj[p]}\n`);
}
}
// 카르테시안 좌표 (x1,x2)과 (x2,y2) 사이의 거리 계산
function distance(x1, y1, x2, y2) {
let dx = x2 - x1;
let dy = y2 - y1;
return Math.sqrt(dx*dx + dy*dy);
}
// 팩토리얼의 계산하는 재귀 함수(자기 자신을 호출)
function factorial(x) {
if (x <= 1) return 1
return x * factorial(x-1);
}
- 함수 표현식 : 일반적인 함수 선언 방법과 비슷하지만 더 큰 표현식이나 문의 일부로서
존재하고 이름을 붙이자 않아도 된다.
// 이 함수 표현식은 인자의 제곱을 계산하는 함수를 정의
// 함수를 변수에 할당
const square = function(x) {return x*x}
// 함수 표현식에도 이름을 쓸 수 있으며 재귀 호출에 유용
const f = function fact(x) { if(x <=1) retunr 1; else return x*fact(x-1);};
// 함수 표현식을 다른 함수의 인자로 사용할 수 있음
[3,2,1].sort(function(a,b) { return a-b;});
// 함수 표현식을 정의하는 즉시 호출할 때도 있음
let tensquard = (function(x) {return x*x;}(10));
- 화살표 함수 : '=>' 기호를 사용해 함수를 정의할 수 있다.
const sum = (x, y) => { return x + y; }
const sum = (x, y) => x + y; // 중괄호 및 return 생략할 수 있음
const polynomial = x => x*x + 2*x + 3; // 매개변수 감싼 괄호도 생략 가능
const constantFunc = () => 42;
const f = x => { return { value: x}; }; // O: f()는 객체를 반환
const g = x => ({ value:x }); // O: g()는 객체를 반환
const h = x => { value: x}; // X: h()는 아무것도 반환하지 않음
const i = x => { v: x, w: x}; // X: 문법 에러
// null 요소를 제거한 배열 사본을 만듦
let filtered = [1,null,2,3].filter(x => x !== null); // filtered == [1,2,3]
// 숫자의 제곱을 구한다.
let squares = [1,2,3,4].map(x => x*x); // squares == [1,4,9,16]
- 중첩된 함수
1) 자바스크립트에서는 다른 함수 안에 함수를 중첩 할 수 있음
2) 중첩된 함수는 자신을 포함하는 함수(들)의 매개변수와 변수를 접근할 수 있음
function hypotenuse(a, b) {
function square(x) { return x*x; }
return Math.sqrt(square(a) + square(b));
}
2. 함수 호출
- 함수로 호출 :
1) 호출 표현식을 통해 함수 또는 메서드 호출
2) 함수 반환 값이 호출 표현식의 값이다. return 문이 없는 경우 undefined를 반환한다.
// 일반적인 호출 표현식
printprops({x: 1});
let total = distance(0,0,2,1) + distance(2,1,3,5)
let probability = factorial(5) / factorial(13)
// 조건부 호출
// ?.를 넣어서 함수가 null이나 undefined가 아닌 경우에만 호출
f?.(x)
(f !== null && f !== undefined) ? f(x) : undefined // 위와 동일한 코드
// 스트릭트 모드에 있는지 확인하는 함수
const strict = (function() {return !this; }());
- 메서드로 호출 :
1) 메서드는 객체 프로퍼티로 저장된 자바스크립트 함수임
2) this를 통해 객체내에 정의된 객체의 값을 사용 가능
3) 대괄호 표현식 및 배열의 인덱스를 통해 호출 가능
4) 메서드 객체를 반환하면 그 반환 값에서 다시 메서드를 호출하는 메서드 체인 사용
let caculator = {
operand1: 1,
operand2: 1,
add() { // 메서드 단축 문법 사용
// this 키워드는 포함하는 객체를 참조
this.result = this.operand1 + this.operand2
}
}
calculator.add() // 메서드 호출을 통해 1+1을 계산
calculator.result // => 2
// 대괄호 표현식
o["m"](x,y); //o.m(x,y)와 동등
a[0](z) //a[0]이 함수라면 역시 메서드 호출
// 메서드 체인
// 세가지 비동기 동작을 순서대로 실행하고 에러를 처리
doStepOne().then(doSteopTwo).then(dotStepThree).catch(handlerErros);
// this
// 1) this 키워드는 변수의 스코프 규칙을 따르지 않는다.
// 2) 화살표 함수의 예외를 제외하면 중첩된 함수는 포함하는 함수의
this 값을 상속하지 않는다.
// 3) 중첩된 함수를 메서드로 호출하면 그 this 값은 호출된 객체이다.
// 4) (화살표 함수가 아닌) 중첩된 함수를 함수로 호출하면 일반모드에서는
this는 전역객체이고 스트릭트모드에서는 undefined이다.
let obj = {
m:function() { // 객체의 메서드 m
let self = this; // this 값을 변수에 저장
this === obj; // => true: this는 객체 obj이다.
f(); // 보조 함수 f() 호출한다.
function f() {
this === obj // => false: this는 전역객체이거나 undefined임
self === obk // => true: self는 obj 값임
}
//화살표 함수를 사용하면
const f2 = () => {
this === obj // => true: 화살표 함수는 항상 this를 상속
}
// bind 함수 사용
const f3 = (function() {
this == 0 // true: 이 함수를 외부 this와 연결
}).bind(this)
}
};
obj.m(); // 객체 obj에서 메서드 m을 호출
- 생성자로 호출
1) 함수난 메서드를 호출할 때 앞에 키워드 new를 붙이면 생성자로 호출
2) 생성자를 호출하면 생성자의 prototype 프로퍼티에서 지정된 객체를
상속하는 빈 객체를 새로 생성(객체 초기화 목적)
3) 생성자 함수는 새 객체를 this 키워드로 참조 가능
4) return 키워드를 사용하지 않음
- 간접적 호출
1) call(), apply()는 함수를 간접적으로 호출, 호출시점에 this값을 직접 명시 가능
2) call() 메서드는 인자 리스트를 받고, apply() 메서드는 인자로 배열을 받음
- 묵시적 호출
1) 함수를 묵시적으로 호출하면 버그, 부작용, 성능 문제 야기
2) 객체에 게터나, 세터가 있다면 프로퍼티 값에 접근할 때 묵시적 메서드가 호출될 수 있음
3) 문자열을 받는 컨텍스트에 객체를 사용한다면 toString() 메서드가 호출
마찬가지로, 객체를 숫자 컨텍스트에 사용하면 valueOf() 메서드가 호출
4) 이터러블 객체의 요소에 순회할 때 여러 가지 메서드가 호출될 수 있음
5) 태그된 템플릿 리터럴 함수 호출을 일으킬 수 있음
6) 프록시 객체는 완전한 함수에 의해 제어되며, 이 객체는 어떤 동작을 취하든 함수가 호출