오늘도 어제에 이어서 underscore.js 라이브러리의 일부를 직접 구현해보는 시간을 가졌다.
그렇다면 지금부터 오늘 직접 구현해본 라이브러리를 설명해보겠다.
1) ._take
배열이 주어진 값을 포함하는지 확인한다.
_.includes = function (arr, target) { let type = false; _.each(arr, function(el) { //각 요소에 반복 적용한다. if(el === target) { //요소가 target이랑 일치한다면 type = true; //주어진 값을 포함한다고 판단한다. } }) return type; };
2)._every
배열의 모든 요소가 함수 iteratee를 통과하면 true를, 그렇지 않은 경우 false를 리턴한다.
_.every = function (arr, iteratee) { let result = true; _.each(arr, function(el) { //각 요소에 반복 적용한다. if(typeof iteratee !== 'function') { //iteratee가 주어지지 않은 경우 if(el !== true) { // 모든 요소가 truthy인지 확인한다. result = false; } } else if(!iteratee(el)) { //모든 요소 중 하나라도 통과하지 못한다면 result = false; } }) return result; };
3)._some
배열의 요소 중 하나라도 test 함수(iteratee)를 통과하면 true를, 그렇지 않은 경우 false를 리턴한다.
_.some = function (arr, iteratee) { let result = false; _.each(arr, function(el) { //각 요소에 반복 적용한다. if(typeof iteratee !== 'function') { //iteratee가 주어지지 않은 경우 if(el !== false) { //모든 요소 중 하나라도 truthy한지 확인한다. result = true; } } else if(iteratee(el)) { //모든 요소 중 하나라도 통과한다면 result = true; } }) return result; };
4)._extend
여러 개의 객체를 입력받아, 순서대로 객체를 결합한다. 단, 첫 번째 입력인 객체를 기준으로 다음 순서의 객체들의 속성을 덮어쓴다.
_.extend = function (...obj) { //여러 개의 객체를 입력받는다. let firstObj = obj[0]; _.each(obj, function(el) { //각 요소에 반복 적용한다. for(let key in el) { firstObj[key] = el[key]; //첫번째로 입력된 객체에 추가한다. } }) return firstObj; };
5)._default
여러 개의 객체를 입력받아, 순서대로 객체를 결합한다. 단, 첫 번째 입력인 객체를 기준으로 다음 순서의 객체들의 속성을 덮어쓴다. 또한 이미 존재하는 속성(key)을 덮어쓰지 않는다.
_.defaults = function (...obj) { //여러 개의 객체를 입력받는다. let firstObj = obj[0]; _.each(obj, function(el) { //각 요소에 반복 적용한다. for(let key in el) { if(firstObj[key] === undefined) { //이미 존재하는 속성이 아니라면 firstObj[key] = el[key]; //첫번째로 입력된 객체에 추가한다. } } }) return firstObj; };
6)._zip
여러 개의 배열을 입력받아, 같은 index의 요소들을 묶어 배열로 만든다. 단, 최종적으로 리턴되는 배열의 각 요소의 길이는 입력으로 전달되는 배열 중 가장 '긴' 배열의 길이로 통일된다.
_.zip = function (...arr) { //여러 개의 배열을 입력받는다. let newArr = []; let result = []; let long; _.map([...arr], function(el){ newArr.push(el.length); //각 배열의 길이를 구한다. }); long = Math.max(...newArr); //가장 긴 배열의 길이를 구한다. for(let j = 0; j < long; j++){ //가장 긴 배열의 길이만큼 반복한다. newArr = []; for(let i = 0; i < arr.length; i++){ //배열의 길이만큼 반복한다. newArr.push(arr[i][j]); //같은 인덱스(i)의 요소들을 추가한다. } result.push(newArr); } return result; };
7)_.zipStrict
여러 개의 배열을 입력받아, 같은 index의 요소들을 묶어 배열로 만든다. 단, 최종적으로 리턴되는 배열의 각 요소의 길이는 입력으로 전달되는 배열 중 가장 '짧은' 배열의 길이로 통일된다.
_.zipStrict = function (...arr) {//여러 개의 배열을 입력받는다. let newArr = []; let result = []; let short; _.map([...arr], function(el){ newArr.push(el.length); //각 배열의 길이를 구한다. }); short = Math.min(...newArr); //가장 짧은 배열의 길이를 구한다. for(let j = 0; j < short; j++){ //가장 짧은 배열의 길이만큼 반복한다. newArr = []; for(let i = 0; i < arr.length; i++){ //배열의 길이만큼 반복한다. newArr.push(arr[i][j]); //같은 인덱스(i)의 요소들을 추가한다. } result.push(newArr); } return result; };
8)._intersection
여러 개의 배열을 입력받아, 교집합 배열을 리턴한다. 단, 교집합 배열의 요소들은 첫 번째 입력인 배열을 기준으로 한다.
_.intersection = function (firstArr, ...arr) { for(let i = 0; i < arr.length; i++) { firstArr = _.filter(firstArr, function(el) { //첫 번째 배열을 기준으로 한다. return _.includes(arr[i], el); //교집합이 있는지 확인하고 있으면 리턴한다. }) } return firstArr; };
9)._difference
여러 개의 배열을 입력받아, 차집합 배열을 리턴한다. 단, 차집합 배열의 요소들은 첫 번째 입력인 배열을 기준으로 한다.
_.difference = function (firstArr, ...arr) { for(let i = 0; i < arr.length; i++) { firstArr = _.filter(firstArr, function(el) { //첫 번째 배열을 기준으로 한다. if(!_.includes(arr[i], el)) { //교집합이 있는지 확인하고 없으면 리턴한다. return true; } }) } return firstArr; };
오늘은 라이브러리를 직접 구현해보는 시간을 가졌다.
내일은 재귀에 대하여 공부한다.
오늘은 여기까지~