[코드 정리 & method 역할] 7주차

Soozynn·2021년 8월 31일
0

[ lodash 라이브러리 만들어보기 ]


.identity

인수로 전달된 값을 반환합니다.
이 함수는 별로 유용해 보이지는 않지만 기억하십시오.
함수가 반복자를 전달하지 않을 때 반복자를 제공해야 하는 경우 이 방법이 편리할 것입니다.

_.identity = function (val) {
  return val;
};

.first

배열의 처음 n개 요소의 배열을 반환합니다.
n이 정의되지 않은 경우, 첫 번째 요소만 반환합니다.

_.first = function (array, n) {
   return n === undefined ? array[0] : array.slice(0, n);
 };

.last

.first와 같지만 n이 정의되지 않은 경우, 마지막 요소를 반환합니다.
n이 0일 경우, 빈 배열을 반환하고, 뒤에서부터 값을 가져옵니다.

 _.last = function (array, n) {
   if (n === 0) return []; // n 이 0일 경우는 빈 배열을 반환

   return n === undefined ? array[array.length - 1] : array.slice(-n);
 };

_.each -> forEach()와 유사

컬렉션의 각 요소에 대해 iterator(value, key, collection)를 호출합니다.
배열과 개체를 모두 허용해야 함

참고: _.each 에는 반환 값이 없지만 입력 컬렉션의 각 항목에 대해 반복기 함수를 실행합니다.

  _.each = function (collection, iterator) {
    if (Array.isArray(collection)) {
      for (let i = 0; i < collection.length; i++) {
        iterator(collection[i], i, collection);
      }
    } else if (typeof collection === "object" && collection !== null) {
      for (const key in collection) {
        if (Object.prototype.hasOwnProperty.call(collection, key)) {
          iterator(collection[key], key, collection);
        }
      }
    }
  };

.indexOf

배열에서 값을 찾을 수 있는 인덱스를 반환하거나 배열에 값이 없으면 -1 을 반환합니다.
해당하는 값이 여러 개이면 제일 첫 번째 인덱스를 반환.

_.indexOf = function (array, target) {
    var result = -1;

    _.each(array, function (item, index) {
      if (item === target && result === -1) {
        result = index;
      }
    });

    return result;
  };

위 코드에서 조건문으로 왜 result === -1 조건도 적혀있을까 하고 조건문에서 해당 값을 지워보니,
테스트 상에서 일치하는 해당 값이 여러 개가 있을 때에 첫번째 인덱스를 반환하는 조건이 통과하지 못하였다.
따라서 이와 같은 조건을 걸어준 이유는 이 때문인 것 같은데....

계속해서 이해를 못하다가 깨달았다..

-> ⭐ 다시 정리해보기 ⭐
if (item === target) 라는 조건만 있을 시에는 해당 배열에 일치하는 요소가 여러 개 있을 때, 일치하는 요소 중 제일 마지막 인덱스 값을 리턴하게 된다. 일치하는 값이 여러 개이면 순회를 하면서 계속해서 result 값이 변하기 때문이다.

(즉, each 함수 내에서 for문이 도는 횟수는 배열의 길이만큼 순회를 하기 때문에 해당 조건이 없을 시에는 최종으로 뱉어내는 인덱스 값이 일치하는 마지막 요소의 인덱스가 되어버린다. 그렇다면 해당 요소를 발견했을 시에 바로 break를 걸어주는게 더 효율적이지 않을까? 하는 생각이 든다.. )

따라서, 초기 값으로 var result = -1; 의 값을 선언하고 조건문에 해당 로직을 추가하게 되면, 제일 처음의 일치하는 요소의 인덱스 값을 뱉게 된다.

이유는 첫 요소를 순회 할 때엔 result 값이 -1 로 선언이 되어있기 때문이다. 위에서 말한 것처럼 일치하는 요소가 여러 개면 계속해서 result 값이 변화하기 때문에 처음의 result 값을 선언해준 거와 같이 조건문을 지정하게되면 제일 처음의 일치하는 요소의 인덱스를 리턴한다.

.filter

주어진 함수의 테스트를 통과하는 모든 요소를 모아 새로운 배열로 반환합니다.

_.filter = function (collection, test) {
  const result = [];

  _.each(collection, function (item) {
    if (test(item)) {
      result.push(item);
    }
  });

  return result;
};

위에 _.each 메서드 에서 첫 번째 인자 값으로 collection, 두 번째 값으로 iterator 을 인자로 받았기 때문에 익명함수는 iterator 를 뜻한다.

filter 의 인자 test 에서 각 요소인 itemtrue 값일 때 result 변수에 담기는 원리이다.

익명함수는 iterator 을 뜻하게 되므로 배열일 경우 _.each 메서드 에서 iterator(collection[i], i, collection); 첫 번째 인자로 각 요소, 두 번째 인자로 index 를 받으므로 익명함수의 item 은 첫 번째 인자인 각 요소를 뜻하게 된다.

.reject

filter 와 반대로 통과하지 않는 모든 요소를 모아 새로운 배열로 반환합니다.

_.reject = function (collection, test) {
    return _.filter(collection, item => !test(item));
  };

filter 와는 반대로 통과하지 않는 값을 반환하기 때문에 not operator를 이용하여 값을 반환하였다.

.map

배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환합니다.

 _.map = function (collection, iterator) {
    const result = [];

    _.each(collection, function (item) {
      result.push(iterator(item));
    });

    return result;
  };

filter와 each와 비슷해보지만 어느 조건 없이 모든 요소에 함수를 실행시키므로(each와 유사) 위와 같이 이츠 메서드를 이용하여 값을 반환하였다.

.reduce

배열의 각 요소에 대해 주어진 리듀서(reducer) 함수를 실행하고, 하나의 결과값을 반환합니다.

 _.reduce = function (collection, iterator, accumulator) {
    let accumulatorCopy = accumulator;
    let collectionCopy = collection;

    if (accumulator === undefined) {
      accumulatorCopy = collection[0];
      collectionCopy = collection.slice(1);
    }

    _.each(collectionCopy, function (item) {
      accumulatorCopy = iterator(accumulatorCopy, item);
    });

    return accumulatorCopy;
  };

⭐ 인자의 값을 함부로 재정의 해줄 경우, arguments의 인자가 혼동이 있을 수 있다.
때문에 해당 인자 값을 변수에 카피해서 사용하였다.

.contains

해당 요소를 포함하면 true, 그렇지 않을 경우 false를 반환합니다.

  _.contains = function (collection, target) {
    return _.reduce(
      collection,
      function (wasFound, item) {
        if (wasFound) {
          return true;
        }

        return item === target;
      },
      false
    );
  };

.every

배열 안의 모든 요소가 주어진 판별 함수를 통과하는지 테스트합니다. Boolean 값을 반환합니다.

 _.every = function (collection, iterator = _.identity) {
  // TIP: Try re-using reduce() here.
  return _.reduce(
    collection,
    function (wasFound, item) {
      if (!wasFound) {
        return false;
      }

      return !!iterator(item);
    },
    true
  );
};

.some

배열 안의 어떤 요소라도 주어진 판별 함수를 통과하는지 테스트합니다.




[정리]


반복문 종류

  1. for문 :고전적인 반복문

  2. for...of: 이터러블 순회 전용

  3. for...in: 객체의 프로퍼티 키 열거 전용 (프로토타입 체인 주의)

  4. forEach(): 배열 순회 전용 메서드

  5. while: 고전적인

  6. do...while: 유일하게 세미콜론으로 마침

  7. Object 객체 메서드: 객체 순회 전용

    • Object.keys()
    • Object.values()
    • Object.entires()
  8. Array.prototye 메서드 : 배열 전용


<짚고 넘어가기>

이번주차 과제.. .each 함수 구현 부분..에서

{ d: "dog", e: "elephant", f: "flotsam" }; 에서 "키 값"과 "벨류 값"을 가져오는 부분에서 혼동이 있었다.
collection[key] -> value 값을 가져오게 되고 key -> key 값을 가져오게 된다.

즉 객체의 value값을 가져오기 위해서는 👉 해당 객체 변수명 [불러올 value의 key 값]..

value 값을 가져올 때에 dot notation 또는 대괄호 [] 를 이용하여 값을 가져오는 것이 규칙인데 숫자나 문자열같은 경우는 대괄호[] 를 이용하여 가져와야하고 그 외는 dot notation 사용이 가능하다



Object.메소드를 보기에 앞서 for...in문Object 메소드 와의 차이는
for-in루프프로토 타입 체인의 속성도 열거한다는 점이다.



Object.entires()

for...in와 같은 순서로 주어진 객체 자체의 enumerable 속성 [key, value] 쌍의 배열을 반환합니다.

// Or, using array extras
Object.entries(obj).forEach(([key, value]) => {
console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
});


// array like object
const obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.entries(obj)); // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]


// example
const object1 = {
  a: 'somestring',
  b: 42
};

for (const [key, value] of Object.entries(object1)) {
  console.log(`${key}: ${value}`); 
  // "a: somestring", "b: 42"

개인적으로 for...in 문 보다 Object.entires 를 쓰는 것이 프로토타입 체인을 타지 않으므로 더 나은 것 같다..



Object.keys()

주어진 객체의 속성 이름들을 일반적인 반복문과 동일한 순서로 순회되는 열거할 수 있는 배열로 반환합니다.

const object1 = {
  a: 'somestring',
  b: 42,
  c: false
};

console.log(Object.keys(object1));
// expected output: Array ["a", "b", "c"]


Object.values()

전달된 파라미터 객체가 가지는 (열거 가능한) 속성의 값들로 이루어진 배열을 리턴합니다. 이 배열은 for...in 구문과 동일한 순서를 가집니다.

const object1 = {
  a: 'somestring',
  b: 42,
  c: false
};

console.log(Object.keys(object1));
// expected output: Array ["a", "b", "c"]

0개의 댓글