underscore.js는 자바스크립트 라이브러리로,
컬럭션, 배열을 처리하는데 유용한 함수들이 제공된다.
오늘은 그 라이브러리의 기능을 구현해보는 실습을 했다.
기존에도 사용했었던 메서드 들도 있었는데, 이들이 어떤 과정으로 동작하는지를
오늘 실습을 하면서 다시 복습해보는 시간이 되어서 나름 좋았다.
오늘 공부한 underscore.js 목록이다.
- _.identity
- _.slice
- _.take
- _.drop
- _.last
- _.each
- _.indexOf
- _.filter
- _.reject
- _.uniq
- _.map
- _.pluk
- _.reduce
_.identity는 전달인자(argument)가 무엇이든, 그대로 리턴한다.
_.identity = function (val) { // 전달인자로 val가 주어졌을때,
return val; // val를 그대로 return해준다.
};
_.slice는 배열의 start 인덱스부터 end 인덱스 이전까지의 요소를
shallow copy하여 새로운 배열을 리턴한다.
_.slice = function (arr, start, end) { // 배열과, 시작, 종료인덱스를 받는다.
let _start = start || 0, // `start`가 undefined인 경우, slice는 0부터 동작한다.
_end = end;
/*
입력받은 인덱스가 음수일 경우, 마지막 인덱스부터 매칭한다.
입력받은 인덱스는 0 이상이어야 한다.
`end`가 생략될 경우(undefined), slice는 마지막 인덱스까지 동작한다.
`end`가 배열의 범위를 벗어날 경우, slice는 마지막 인덱스까지 동작한다.
*/
if (start < 0) _start = Math.max(0, arr.length + start);
if (end < 0) _end = Math.max(0, arr.length + end);
if (_end === undefined || _end > arr.length) _end = arr.length;
let result = []; // `start`가 배열의 범위를 벗어날 경우, 빈 배열을 리턴한다.
for (let i = _start; i < _end; i++) {
result.push(arr[i]);
}
return result;
};
_.take는 배열의 처음 n개의 element를 담은 새로운 배열을 리턴한다.
_.take = function (arr, n) { // 배열과 n을 입력받는다
let result = []; // 빈 배열을 선언해준다.
if (n < 0 && n === undefined) return []; // n이 음수이거나, 입력받지 않았을때, 빈배열을 리턴한다.
if (n > arr.length) return arr; // n이 배열의 길이보다 클때, 배열을 그대로 리턴한다.
for (let i = 0; i < n; i++) { // 주어진 n을 이용해 반복문을 생성한다.
result.push(arr[i]); // 반복문에 해당되는 요소들을 빈배열에 push한다.
}
return result; // 최종 result를 return 해준다.
};
.drop는 .take와는 반대로, 처음 n개의 element를 제외한 새로운 배열을 리턴한다.
_.drop = function (arr, n) {
let result = [];
if (n < 0 || n === undefined) return arr;
for (let i = n; i < arr.length; i++) {
result.push(arr[i]);
}
return result;
};
_.last는 배열의 마지막 n개의 element를 담은 새로운 배열을 리턴한다.
_.last = function (arr, n) {
let result = [];
if (n === undefined) return [arr[arr.length - 1]];
if (n === 0) return [];
if (n > arr.length) return arr;
for (let i = arr.length - n; i < arr.length; i++) {
result.push(arr[i])
}
return result;
};
_.each는 collection의 각 데이터에 반복적인 작업을 수행한다.
/*
1. collection(배열 혹은 객체)과 함수 iteratee(반복되는 작업)를 인자로 전달받아
(iteratee는 함수의 인자로 전달되는 함수이므로 callback 함수)
2. collection의 데이터(element 또는 property)를 순회하면서
3. iteratee에 각 데이터를 인자로 전달하여 실행합니다.
*/
_.each = function (collection, iteratee) {
if (Array.isArray(collection)) {
for (let i = 0; i < collection.length; i++) {
iteratee(collection[i], i, collection);
}
} else if (typeof collection === "object") {
for (let key in collection) {
iteratee(collection[key], key, collection);
}
}
};
_.indexOf는 target으로 전달되는 값이 arr의 요소인 경우, 배열에서의 위치(index)를 리턴한다.
_.indexOf = function (arr, target) {
// 반복문을 사용하는 것이 가장 일반적이지만, 지금부터는 이미 구현한 _.each 함수를 활용한다.
let result = -1;
_.each(arr, function (item, index) {
if (item === target && result === -1) {
result = index;
}
});
return result;
};
_.filter는 test 함수를 통과하는 모든 요소를 담은 새로운 배열을 리턴한다.
_.filter = function (arr, test) {
let result = [];
_.each(arr, function (num) {
if (test(num)) {
result.push(num)
}
});
return result;
};
.reject는 .filter와 정반대로 test 함수를 통과하지 않는 모든 요소를 담은 새로운 배열을 리턴한다.
_.reject = function (arr, test) {
코드를 입력하세요
let result = [];
_.each(arr, function (num) {
if (!test(num)) {
result.push(num)
}
});
return result;
};
_.uniq는 주어진 배열의 요소가 중복되지 않도록 새로운 배열을 리턴한다.
_.uniq = function (arr) {
let result = [];
_.each(arr, function (num) {
if (_.indexOf(result, num) === -1) {
result.push(num)
}
});
return result;
};
_.map은 iteratee(반복되는 작업)를 배열의 각 요소에 적용한 결과를 담은 새로운 배열을 리턴한다.
_.map = function (arr, iteratee) {
// _.each 함수와 비슷하게 동작하지만, 각 요소에 iteratee를 적용한 결과를 리턴한다.
let result = [];
_.each(arr, function(el){
result.push(iteratee(el))
})
return result;
};
_.pluck은
1. 객체 또는 배열을 요소로 갖는 배열과 각 요소에서 찾고자 하는 key 또는 index를 입력받아
2. 각 요소의 해당 값 또는 요소만을 추출하여 새로운 배열에 저장하고,
3. 최종적으로 새로운 배열을 리턴한다.
_.pluck = function (arr, keyOrIdx) {
let result = [];
_.map(arr, function(el){
result.push(el[keyOrIdx]);
})
return result;
};
_.reduce는
1. 배열을 순회하며 각 요소에 iteratee 함수를 적용하고,
2. 그 결과값을 계속해서 누적한다.
3. 최종적으로 누적된 결과값을 리턴한다.
_.reduce = function (arr, iteratee, initVal) {
let result = initVal;
_.each(arr, function(el, indx, arr){
if(result === undefined) {
result = el;
}else{
result = iteratee(result, el, indx, arr)
}
});
return result;
};