// 함수명 set'Price'ByName의 Price가 암묵적 인자
function setPriceByName(cart, name, price) {
var item = cart[name]; // 인자
var newItem = objectSet(item, 'price', price);
var newCart = objectSet(cart, name, newItem);
}
cart = setPriceByName(cart, "shoe", 20000)
// 명시적 인자 field를 추가
// 원래 인자는 더 명시적인 이름 value로 바꿈
function setFieldByName(cart, name, field, value) {
var item = cart[name];
var newItem = objectSet(item, field, value);
var newCart = objectSet(cart, name, newItem);
}
cart = setFieldByName(cart, "shoe", 'price', 20000)
function obejctSet(object, key, value) {
var copy = Object.assign({}, object);
copy[key] = value;
return copy;
}
Object.assign(target, ...sources)
- 매개변수 target
목표 객체. 출처 객체의 속성을 복사해 반영한 후 반환할 객체입니다.
- sources
출처 객체. 목표 객체에 반영하고자 하는 속성들을 갖고 있는 객체들입니다.
// 예시
const obj = { a: 1 };
const copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
-> 이제 암묵적인 이름은 인자로 넘길 수 있는 값(여기서는 문자열)이 됨
-> 값은 변수나 배열에 담을 수 있고 그래서 일급(frist-class)라 부름
// 원래 코드
try {
saveUserData(user);
} catch (error) {
logToSnapErrors(error);
}
// 함수로 빼내기
function withLogging() {
try {
saveUserData(user); // 콜백으로 빼낼 예정
} catch (error) {
logToSnapErrors(error);
}
}
// 콜백으로 빼내기
function withLogging(f) {
try {
f(); // 콜백으로 빼내어 아래에서 본문 전달
} catch (error) {
logToSnapErrors(error);
}
}
withLogging(function() {
saveUserData(user);
});
// 원래 코드 - copy on write
function arraySet(array, idx, value) {
var copy = array.slice();
copy[idx] = value;
return copy;
}
// 함수로 빼내기
function arraySet(array, idx, value) {
return withArrayCopy(array);
}
function withArrayCopy(array) {
var copy = array.slice();
copy[idx] = value; // idx와 value를 위에서 알 수 없어서 동작 x
}
// 콜백 빼내기
function arraySet(array, idx, value) {
return withArrayCopy(array, function(copy) {
copy[idx] = value; // 필요한 부분을 인자로 만들어 전달
});
}
function withArrayCopy(array, modify) {
var copy = array.slice();
modify(copy); // 콜백
return copy;
}
반복문을 활용하여 다양한 종류의 email 보내기
// Code from chapter 3
function emailsForCustomers(customers, goods, bests) {
var emails = [];
for(var i = 0; i < customers.length; i++) {
var customer = customers[i];
var email = emailForCustomer(customer, goods, bests);
emails.push(email);
}
return emails;
}
// Using forEach()
function emailsForCustomers(customers, goods, bests) {
var emails = [];
forEach(customers, function(customer) {
var email = emailForCustomer(customer, goods, bests);
emails.push(email);
});
return emails;
}
// forEach()
function forEach(array, f) {
for (var i = 0; i < array.length; i++) {
var item = array[i];
f(item);
}
}
반복문 대신 map()을 활용하기
/// Original Code
function emailsForCustomers(customers, goods, bests) {
var emails = [];
forEach(customer, function(customer) {
var email = emailForCustomer(customer, goods, bests); // 본문
emails.push(email);
});
return emails;
}
function biggestPurchasePerCustomer(customers) {
var purchases = [];
forEach(customer, function(customer) {
var customer = customers[i];
var purchase = biggestPurchase(customer); // 본문
purchases.push(purchase);
});
return purchases;
}
/// 본문을 콜백으로, forEach()는 map()으로 빼내 일반적인 함수로 변경
function emailsForCustomers(customers, goods, bests) {
return map(customers, function(customer) { // 본문을 콜백으로 전달
return emailForCustomer(customer, goods, bests);
});
}
function biggestPurchasePerCustomer(customers) {
return map(customers, function(customer) { // 본문을 콜백으로 전달
return biggestPurchase(customer);
});
}
function map(array, f) {
var newArray = [];
forEach(array, function(element) {
newArray.push(f(element)); // 콜백 부름
});
return newArray;
}
// 순서 : emailsForCustomers() -> map -> forEach()
// -> 콜백함수(emailForCustomer) -> return newArray
/// Original Code
function selectBestCustomers(customers) {
var newArray = [];
forEach(customers, function(customer) {
if(customer.purchases.length >= 3) // 본문이 표현식
newArray.push(customer);
});
return newArray;
}
/// 본문은 콜백으로, 이외의 부분은 filter()로 빼내기
function selectBestCustomers(customers) {
return filter(customers, function(customer) {
return customer.purchases.length >= 3 // 본문
})
}
function filter(array, f) {
var newArray = [];
forEach(array, function(element) {
if (f(element)) { // 조건식을 콜백으로 부름
newArray.push(element);
}
});
return newArray;
}
/// Original Code
function countAllPurchases(customers) { // 달라지는 부분
var total = 0; // 초기값
forEach(customers, function(customer) {
total = total + customer.purchases.length; // 본문
});
return total;
}
/// 초기값과 본문 외에 reduce()로 빼내기
function countAllPurchases(customers) {
return reduce(customers, 0, function(total, customer) { // 초기값과 본문
return total + customer.purchases.length;
});
}
function reduce(array, init, f) {
var accum = init;
forEach(array, function(element) {
accum = f(accum, element);
});
return accum;
}
// reduce()를 활용해 배열에서 가장 작은 값 찾기
function min(numbers) {
return reduce(numbers, Number.MAX_VALUE, function(m, num) {
if (m < num) return m;
else return num;
});
}
/// Original Code
function incrementField(item, field) {
var value = item[field];
var newValue = value + 1;
var newItem = objectSet(item, field, newValue);
return newItem;
}
/// Extracted update
function incrementField(item, field) {
return updateField(item, field, function(value) {
return value + 1;
});
}
function updateField(item, field, modify) {
var value = item[field];
var newValue = modify(value);
var newItem = objectSet(item, field, newValue);
return newItem;
}
/// Called update()
function update(object, key, modify) {
var value = object[key];
var newValue = modify(value); // 바뀌는 부분
var newObject = objectSet(object, key, newValue);
return newObject;
}
다음장에서 계속