2021_03_24

유지원·2021년 3월 24일
1
post-thumbnail

TIL - 라이브러리 직접 구현하기

1. 라이브러리 직접 구현하기

오늘도 어제에 이어서 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;
};




오늘은 라이브러리를 직접 구현해보는 시간을 가졌다.
내일은 재귀에 대하여 공부한다.
오늘은 여기까지~

profile
안녕하세요 유지원입니다

0개의 댓글