오늘은 비동기 챕터를 본격적으로 들어가기 전에 고차함수와 Callback 함수에 대해서 복습하고 배열 메소드가 브라우저에서 지원되지 않을때 사용하던 underscroe.js 라이브러리를 실제로 구현하는 스프린트를 진행하였다.
_.identity = function (val) {
return val;
};
_.slice = function (arr, start, end) {
let _start = start || 0,
_end = end;
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 = [];
for (let i = _start; i < _end; i++) {
result.push(arr[i]);
}
return result;
};
_.take = function (arr, n) {
let result = [];
if (n < 0 || n === undefined) {
return result;
}
if (n >= arr.length) {
return arr;
}
for(let i = 0; i < n; i++) {
result.push(arr[i])
}
return result;
};
_.drop = function (arr, n) {
let result = [];
if (n < 0 || n === undefined) {
return arr;
}
if (n > arr.length) {
return result;
}
for (let i = n; i < arr.length; i++) {
result.push(arr[i])
}
return result;
};
_.each = function (collection, iteratee) {
if (Array.isArray(collection)) {
for (let i = 0; i < collection.length; i++) {
iteratee(collection[i], i, collection)
}
}
else {
for (let key in collection) {
iteratee(collection[key], key, collection)
}
}
};
_.indexOf = function (arr, target) {
let result = -1;
_.each(arr, function (item, index) {
if (item === target && result === -1) {
result = index;
}
});
return result;
};
_.filter = function (arr, test) {
let result = [];
_.each(arr, (el) => {
if (test(el)) {
result.push(el)
}
})
return result;
};
_.reject = function (arr, test) {
let result = [];
_.each(arr, (el) => {
if (!test(el)) {
result.push(el)
}
})
return result;
};
_.uniq = function (arr) {
let result = [];
_.each(arr, (el) => {
if (_.indexOf(result, el) === -1) {
result.push(el);
}
})
return result;
};
_.map = function (arr, iteratee) {
let result = [];
_.each(arr, (el) => {
result.push(iteratee(el));
})
return result;
};
_.pluck = function (arr, keyOrIdx) {
return _.map(arr, (el) => {
return el[keyOrIdx];
})
};
_.reduce = function (arr, iteratee, initVal) {
if (initVal === undefined) {
initVal = arr[0];
arr = _.slice(arr, 1)
}
_.each(arr, (el, i, reduceArr) => {
initVal = iteratee(initVal, el, i, reduceArr)
})
return initVal;
};
_.once = function (func) {
let isCalled = false;
let result
return function () {
if(!isCalled) {
isCalled = true
result = func(...arguments)
}
return result
};
};
_.delay = function (func, wait) {
setTimeout(...arguments)
};
_.includes = function (arr, target) {
let result = false
_.each(arr, (el) => {
if (el === target) result = true
})
return result
};
_.every = function (arr, iteratee) {
if(arr.length === 0) return true
if(!iteratee){
iteratee = _.identity;
}
for(let i=0; i < arr.length; i++){
if(!iteratee(arr[i])){
return false;
}
}
return true;
};
_.some = function (arr, iteratee) {
if(arr.length === 0) return false
if(!iteratee){
iteratee = _.identity;
}
for(let i=0; i < arr.length; i++){
if(iteratee(arr[i])){
return true;
}
}
return false;
};
_.extend = function () {
_.each(arguments, (el) => {
for(let key in el) {
arguments[0][key] = el[key]
}
})
return arguments[0]// TODO: 여기에 코드를 작성합니다.
};
_.defaults = function () {
_.each(arguments, (el) => {
for(let key in el) {
if(_.includes(Object.keys(arguments[0]),key) === false) {
arguments[0][key] = el[key]
}
}
})
return arguments[0]
};
_.zip = function () {
let arg = [...arguments]
let maxLength = 0;
_.each(arg, (el) => {
if(el.length > maxLength) maxLength = el.length;
})
let result = [];
for (let i=0; i<maxLength; i++) {
let row = [];
for (let j=0; j<arg.length; j++) {
if (arg[j][i] === undefined) row.push(undefined);
else row.push(arg[j][i]);
}
result.push(row);
}
return result;
};
_.zipStrict = function () {
let arg = [...arguments]
let minLength = arguments[0].length;
_.each(arg, (el) => {
if(el.length < minLength) minLength = el.length;
})
let result = [];
for (let i=0; i<minLength; i++) {
let row = [];
for (let j=0; j<arg.length; j++) {
row.push(arg[j][i]);
}
result.push(row);
}
return result;
};
_.intersection = function () {
let result = [];
_.each(arguments[0],(el)=> {
let count =1;
for (let j=1; j<arguments.length; j++) {
if(_.includes(arguments[j],el) === false) {
break;
}
count++
}
if (count === arguments.length) result.push(el)
})
return result
};
_.difference = function () {
let result = [];
_.each(arguments[0],(el)=> {
let count =1;
for (let j=1; j<arguments.length; j++) {
if(_.includes(arguments[j],el)) {
break;
}
count++
}
if (count === arguments.length) result.push(el)
})
return result
};
_.sortBy = function (arr, transform, order) {
transform = transform || _.identity;
let result = _.slice(arr)
if (typeof transform(arr[0]) === 'number') {
if (order === 1 || order === undefined) {
result.sort((a,b) => transform(a)-transform(b));
}
else if (order === -1) {
result.sort((a,b) => transform(b)-transform(a));
}
}
else if (typeof transform(arr[0]) === 'string') {
if (order === 1 || order === undefined) {
result.sort((a,b) => {
if (transform(a) < transform(b)) return -1;
else if (transform(b) < transform(a)) return 1;
else return 0;
})
}
else if (order === -1) {
result.sort((a,b) => {
if (transform(a) > transform(b)) return -1;
else if (transform(b) > transform(a)) return 1;
else return 0;
})
}
}
return result
};
_.shuffle = function (arr) {
let arrCloned = arr.slice();
for (let fromIdx = 0; fromIdx < arr.length; fromIdx++) {
const toIdx = Math.floor(Math.random() * arr.length);
// 아래 코드는 두 변수의 값을 교환합니다.
let temp = arrCloned[fromIdx];
arrCloned[fromIdx] = arrCloned[toIdx];
arrCloned[toIdx] = temp;
}
return arrCloned;
};
기존에 사용했던 배열 메소드들을 직접 구현함으로써 작동원리를 이해하고 앞에서 만든 함수를 활용하면서 메소드들에 대해서 깊게 이해할 수 있었다. setTimeout를 통해서 비동기 챕터 부분을 예습할 수 있었고 arguments에 대해 이해하고 코드를 효율적으로 작성하는 법에 대해서 알 수 있는 시간이었다.