7週目/Underbar


組み込みメソッドライブラリの実装


以前はブラウザで配列方法がサポートされていませんでした
配列やオブジェクトを処理するライブラリツールバーを作成しました.
今回のスプレッドシートでは、配列やオブジェクトを扱うライブラリUnderbarを実装し、JavaScript内蔵メソッドがcallback関数をどのように利用するかを理解しました.

each

_.each
// _.each는 collection의 각 데이터에 반복적인 작업을 수행합니다.
//  1. collection(배열 혹은 객체)과 함수 iteratee(반복되는 작업)를 인자로 전달받아 
//    (iteratee는 함수의 인자로 전달되는 함수이므로 callback 함수)
//  2. collection의 데이터(element 또는 property)를 순회하면서
//  3. iteratee에 각 데이터를 인자로 전달하여 실행합니다.
// _.each는 명시적으로 어떤 값을 리턴하지 않습니다.

 * iteratee는 차례대로 데이터(element 또는 value), 
   접근자(index 또는 key), collection을 다룰 수 있어야 합니다.
 *  배열 arr을 입력받을 경우, iteratee(ele, idx, arr)
 *  객체 obj를 입력받을 경우, iteratee(val, key, obj)
 
各メソッドは、各データに対して繰り返し操作を行います.
文系whileとかの仕事をしているつもりです.
コレクションには、配列またはオブジェクトを含めることができます.
配列とオブジェクトが入るときに受け取るデータが異なるので、異なる条件を与えます.
foreach()の方が問題を解きやすいと思います
_.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 i in collection){
      iteratee(collection[i], i, collection)
    }
  }
};
// 배열과 객체의 타입은 전부 다 object이므로 else가 아닌
// else if로 배열일때 위에서 걸러지게 만들어 줘야한다

reduce


最も困難なreduceの実施
// _.reduce는
//  1. 배열을 순회하며 각 요소에 iteratee 함수를 적용하고,
//  2. 그 결과값을 계속해서 누적(accumulate)합니다.
//  3. 최종적으로 누적된 결과값을 리턴합니다.

// iteratee는 차례대로 데이터(element 또는 value), 접근자(index 또는 key), collection을 다룰 수 있어야 합니다.
//  배열 arr을 입력받을 경우, iteratee(ele, idx, arr)


// _.reduce는 반복해서 값을 누적하므로 이 누적되는 값을 관리해야 합니다.
// 따라서 _.reduce의 iteratee는 인자가 하나 더 추가되어 최종 형태는 아래와 같습니다.
//  iteratee(acc, ele, idx, arr)


// 여기까지 내용을 정리하면 다음과 같습니다.
//  _.reduce(arr, iteratee)
//  iteratee(acc, ele, idx, arr)
// 그런데 사실 누적값에 대해서 빠뜨린 게 하나 있습니다.
// 바로 '누적값은 어디서부터 시작하는가'라는 의문에 대한 대답을 하지 않았습니다.
// 이를 해결하는 방법은 초기 값을 직접 설정하거나 자동으로 설정하는 것입니다.
// _.reduce는 세 번째 인자로 초기 값을 전달받을 수 있습니다.
// 이 세 번째 인자로 초기 값이 전달되는 경우, 그 값을 누적값의 기초(acc)로 하여 배열의 '첫 번째' 요소부터 반복 작업이 수행됩니다.
// 반면 초기 값이 전달되지 않은 경우, 배열의 첫 번째 요소를 누적값의 출발로 하여 배열의 '두 번째' 요소부터 반복 작업이 수행됩니다.

// 따라서 최종적인 형태는 아래와 같습니다.
//  _.reduce(arr, iteratee, initVal)
//  iteratee(acc, ele, idx, arr)
参考例
//  const numbers = [1,2,3];
//  const sum = _.reduce(numbers, function(total, number){
//    return total + number;
//  }); // 초기 값이 주어지지 않았으므로, 초기 값은 배열의 첫 요소인 1입니다. 
       // 두 번째 요소부터 반복 작업이 시작됩니다.
//      // 1 + 2 = 3; (첫 작업의 결과가 누적되어 다음 작업으로 전달됩니다.)
//      // 3 + 3 = 6; (마지막 작업이므로 최종적으로 6이 리턴됩니다.)
//
//  const identity = _.reduce([3, 5], function(total, number){
//    return total + number * number;
//  }, 2); // 초기 값이 2로 주어졌습니다. 첫 번째 요소부터 반복 작업이 시작됩니다.
//         // 2 + 3 * 3 = 11; (첫 작업의 결과가 누적되어 다음 작업으로 전달됩니다.)
//         // 11 + 5 * 5 = 36; (마지막 작업이므로 최종적으로 36이 리턴됩니다.)
各メソッドの使用状況を理解する

_.reduce = function (arr, iteratee, initVal) {
  let accumulator = initVal;

  _.each(arr, function (item, idx, src) {
    // initVal이 없고 인덱스가 0번째이면 
    // 초기값을 넣어준다
    if (initVal === undefined && idx === 0) {
      accumulator = item;
    } else {
      accumulator = iteratee(accumulator, item, idx, src);
    }
  });

  return accumulator;
};
未使用方法の解答
_.reduce = function (arr, iteratee, initVal) {

  let accumulate = initVal;
  if(accumulate === undefined){
    // accumulator에 초기값이 지정되지 않는 경우 
    // 초기값은 collection의 0번째 인덱스 값
    accumulate = arr[0];
    // collection[0]은 이미 초기값으로 사용했으니 
    // for문은 i를 1부터 시작하도록 설정. 
  for(let i = 1; i < arr.length; i++){
    accumulate = iteratee(accumulate, arr[i]);
  }}else{
    // accumulator에 초기값이 지정되는 경우
    for(let j = 0; j < arr.length; j++){
      accumulate = iteratee(accumulate, arr[j])
    }
  }
  // accumulator에 누적된 값을 출력 
  return accumulate
};
1) _.each関数を使用する必要があります
2)iterateは、累積値、要素、インデックス、配列全体を順次入力する必要があります.
方法を用いて解かないと、2つのテストケースは合格できません.