const flight = 'LH234'
const jonas = {
name: 'Jonas Schemedtmann',
passport: 2345667,
}
const checkIn = function (flightNum, passenger) {
flightNum = 'LH999'; // 원시 타입의 값은 함수 안에서 사용할 값을 새로 생성한다.
passenger.name = 'Mr. ' + passenger.name; // 참조 타입의 값은 인자로 넘어온 값을 참조하므로 값이 변경된다.
if (passenger.passport === 2345667) {
alert('Checked in');
} else {
alert('Wrong passport');
}
}
checkIn(flight, jonas);
console.log(flight); // LH234
console.log(jonas); // {name: 'Mr. Jonas Schemedtmann', passport: 2345667}
원시 타입의 값은 함수 안에서 사용할 값을 새로 생성한다.
참조 타입의 값은 인자로 넘어온 값을 참조하므로 값이 변경된다.
자바스크립트는 객체와 같은 참조 타입 인자를 pass in a reference(memory address of object), 하지만 메모리 주소를 가진 ‘값’으로 넘겨준다.
const oneWord = function (str) {
return str.replace(/ /g, '').toLowerCase();
}
const upperFirstWord = function (str) {
const [first, ...others] = str.split(' ');
return [first.toUpperCase(), ...others].join(' ');
};
// Higher-order function
const transformer = function (str, fn) {
console.log(`Transformed string: ${fn(str)}`);
console.log(`Transformed by: ${fn.name}`);
}
transformer('JavaScript is the best!', upperFirstWord);
transformer('JavaScript is the best!', oneWord);
transformer 함수에 넘긴 fn 함수를 콜백 함수라고 부른다.
고차 함수 안에서 실제로 호출될 때 콜백을 하는 함수라는 의미로 이해하면 쉽다.
추상화(Abstraction)을 가능케 하는 기능이다.
추상화: 복잡한 자료, 모듈, 시스템 등으로부터 핵심적인 개념 또는 기능을 간추려 내는 것
자바스크립트를 사용할 때 정말 자주 쓰이는 핵심 기능이다.
함수를 리턴하는 함수(Functions Returning Functions)
const greet = function (greeting) {
return function (name) {
console.log(`${greeting} ${name}`);
}
}
const greeterHey = greet('Hey');
greeterHey('Jonas');
greet('Hello')('Jonas');
// c.f. Using Arrow function
const greetArr = greeting => name => console.log(`${greeting} ${name}`);
greetArr('Hi')('Jonas')
함수형 프로그래밍에서 유용하게 쓰이는 기능이다.
Call & Apply & Bind 메소드
const lufthansa = {
airline: 'Lufthansa',
iataCode: 'LH',
bookings: [],
book(flightNum, name) {
console.log(`${name} booked a seat on ${this.airline} flight ${this.iataCode}${flightNum}`);
this.bookings.push({ flight: `${this.iataCode}${flightNum}`, name });
},
};
lufthansa.book(239, 'Jonas Schmedtmann');
lufthansa.book(635, 'John Smith');
const eurowings = {
airline: 'Eurowings',
iataCode: 'EW',
bookings: [],
}
const book = lufthansa.book;
// regular function call -> this를 사용할 수 없으므로 에러
// book(23, 'Sarah Williams');
this 키워드를 사용하는 객체의 메서드를 외부에서 새로운 함수로 선언하면 어떻게 사용할 수 있을까?
Call 메소드
book.call(eurowings, 23, 'Sara Williams') // 첫번째 인자로 this에 들어갈 객체를 넣는다.
console.log(eurowings);
Apply 메소드
const flightData = [583, 'George Cooper'];
book.apply(eurowings, flightData); // 배열을 넣어야 한다는 차이가 있다.
book.apply(eurowings, [583, 'George Cooper']);
book.call(eurowings, ...flightData);
모던 JS에서는 call 메소드와 스프레드 연산자를 사용하면 되므로 apply 메소드를 잘 사용하지 않는다.
Bind 메소드
const bookEW = book.bind(eurowings);
const bookLH = book.bind(lufthansa);
const bookLX = book.bind(swiss);
bookEW(23, 'Steven Williams');
// preset을 설정할 수 있다.
const bookEW23 = book.bind(eurowings, 23);
bookEW23('Jonas Schemedtmann');
// Partial application
const addTax = (rate, value) => value + value * rate;
console.log(addTax(0.1, 200));
const addVAT = addTax.bind(null, 0.23); // preset으로 설정하지 않을 값은 null로 지정
bind 메소드는 preset을 세팅할 수 있으므로 활용도가 높다.(Partial application)
// with event listeners
lufthansa.planes = 300;
lufthansa.buyPlane = function () {
console.log(this);
this.planes++
console.log(this.planes)
};
lufthansa.buyPlane();
// document.querySelector('.buy').addEventListener
// ('click', lufthansa.buyPlane); // 이 함수의 this는 button이 되어서 정상적으로 작동하지 않음
document.querySelector('.buy').addEventListener
('click', lufthansa.buyPlane.bind(lufthansa)); // bind 메서드를 사용, 새로운 함수를 콜백 함수로 사용
또한 이벤트 리스너의 콜백 함수로 사용할 때 유용하다.
IIFE(Immediately Invoked Function Expressions)
const runOnce = function () {
console.log('This will never run again');
}
runOnce();
// IIFE
(function () {
console.log('This will never run again');
})();
(() => console.log('This will never run again'))();
1회만 호출하고 재사용될 필요 없는 함수를 IIFE로 선언할 수 있다.
선언하고 즉시 호출되므로 Immediately Invoked라고 표현한다.
코드 블럭 안에서 선언된 변수는 블럭 밖에서 접근할 수 없으므로 캡슐화에 사용될 수 있다.
클로저는 함수가 생성된 시점의 유효 범위 내에 있는 모든 지역 변수로 구성되며, 함수가 생성될 때 클로저도 함께 생성된다.
부모 함수가 종료되어 부모 함수의 EC(Execution Context)가 반환되어도 부모 함수의 VE(Variable Environment)=클로저는유효하다.
스코프 체인보다 클로저의 우선순위가 높으므로, JS 엔진은 함수를 실행할 때 클로저의 변수를 먼저 찾아본다.
A closure is the closed-over variable environment of the execution context in which a function was created, even after that execution context is gone.
A closure gives a function access to all the variables of its parent function, event after that parent function has returned. The function keeps a reference to its outer scope, which preserves the scope chain throughout time.