Может кто-нибудь объяснить мне, почему мы использовали фигурные скобки "{}" в этом коде? - PullRequest
1 голос
/ 29 марта 2019

Пока я пытался проверить, сколько раз элемент используется в массиве, я нашел этот код.Это написано другим пользователем, и я заставил его работать, но я пытаюсь выяснить, почему он использовал "{}" в конце.Я знаю, что метод .reduce () может получить initialValue, но я не мог понять использование фигурных скобок.

var a = ["a","b","b","c","a","b","d"];  
 
 var map = a.reduce(function(obj, b) { obj[b] = ++obj[b] || 1;    
 return obj;
  }, {});

Я думал, что они могут быть параметром initialValue, поскольку он покрывает результат, но когда я попытался удалить фигурные скобки, результат был не таким.Я также проверил документы MDN, нашел какой-то похожий код, но не смог обдумать его, так как я совершенно новый в JavaScript.

Когда мы используем скобки, я получаю:

{
  a: 2,
  b: 3,
  c: 1,
  d: 1
}

Но когда я удаляю фигурные скобки и запускаю их, я получаю:

a

Я пытался использовать скобки, и это выглядело как: [a: 2, b: 3, c: 1, d: 1],

Так что, кажется, фигурные скобки заключают значения, но разве не должно работать без скобок?

Ответы [ 5 ]

2 голосов
/ 29 марта 2019

Но когда я снимаю фигурные скобки и запускаю их, я получаю: a

Это синтаксис :

arr.reduce(callback[, initialValue]) 

initialValue: значение, используемое в качестве первого аргумента для первого вызова обратного вызова. Если начальное значение не указано, будет использоваться первый элемент в массиве."

Так что, если вы используете reduce без initialValue ({}), первый элемент в массиве будет использоваться как initialValue, то есть "a"

Таким образом, оно становится похожим на:

var a = ["a", "b", "b", "c", "a", "b", "d"];

var map = a.slice(1).reduce(function(obj, b) {
  obj[b] = ++obj[b] || 1;
  return obj;
}, "a");

console.log(map)

На первой итерации

obj[b] = ++obj[b] || 1;

становится

"a"["b"] = ++"a"["b"] || 1

Это не вызывает исключение и не изменяетobj строка.obj по-прежнему "a" и будет возвращаться каждый раз.

1 голос
/ 29 марта 2019

{} создайте новый объект, если вы не добавите это, тогда будет использоваться первый элемент в массиве.

Вы можете видеть, что когда вы запускаете код с {}, вы получаете пустойобъект как initialValue и выполняет ваше требование.

var a = ["a","b","b","c","a","b","d"];  
 
var map = a.reduce(function(obj, b) { 
    "use strict";

    if (Object.entries(obj).length === 0 && obj.constructor === Object) {
        console.log("InitialValue is defined as object: ", obj);
    }
    obj[b] = ++obj[b] || 1;    
    return obj;
}, {});

console.log(map);

Тогда как без {} первое значение массива a присваивается obj, что означает, что теперь obj является строкой, а когда вы пытаетесь использоватьэто как объект, тогда он выдает ошибку, как в приведенном ниже коде.

var a = ["a","b","b","c","a","b","d"];  
 
var map = a.reduce(function(obj, b) { 
    "use strict";

    console.log("InitialValue not defined: ", obj);
    obj[b] = ++obj[b] || 1;    
    return obj;
});

console.log(map);

Я только что добавил "use strict", чтобы показать эту ошибку.

1 голос
/ 29 марта 2019

Скобки {} представляют новый пустой объект в javascript. В вашем случае это будет объект, возвращаемый методом reduce в переменную map, нам нужно сначала его инициализировать, а затем заполнить в ядро reduce обратного вызова.

Значение, используемое в качестве первого аргумента для первого вызова обратного вызова. Если начальное значение не указано, будет использован первый элемент в массиве. Вызов redu () для пустого массива без начального значения является ошибкой.

Это initialValue . Взгляните на reduce () , вот пример, если бы вы предоставили начальное значение в качестве второго аргумента для уменьшения (), результат будет выглядеть так:

let arr = [0, 1, 2, 3, 4];

arr = arr.reduce((accumulator, currentValue, currentIndex, array) => {
  return accumulator + currentValue;
}, 10);

console.log(arr);
1 голос
/ 29 марта 2019

Вторым аргументом в методе .reduce() является initialValue, который является значением

, используемым в качестве первого аргумента для первого вызова обратного вызова.Если начальное значение не указано, будет использоваться первый элемент массива.


tl; dr

Это начальное значение, которое .reduce() начинается с.Это первый аргумент, переданный обратному вызову в первом вызове.


В вашем случае идея состояла в том, чтобы построить карту значений из массива, где ключами на карте были значения из массива изначения в карте были числом вхождений этого значения в массив.

Карта в JS может быть легко смоделирована объектом, который в вашем случае был передан как литерал {} в .reduce() метод.Метод запускает функцию обратного вызова для каждого элемента в массиве, передавая объект результата в качестве первого аргумента и текущий элемент в массиве в качестве второго.Но проблема заключается в первом вызове - какое значение следует использовать в качестве объекта результата, если в массиве не было предыдущих элементов для накопления?Вот почему вам нужно передать какое-то начальное значение, чтобы было с чего начать.Как говорится в MDN, если не передано initialValue, используется первый элемент массива - поэтому вы получили a при удалении начального значения.Когда вы передали [], вы сказали JS, чтобы в качестве начального значения использовался литерал массива, но в обратном вызове вы рассматривали его как объект, который разрешен в JS, поскольку массив также является объектом.Проблема возникает, когда вы пытаетесь перебрать эти свойства или привести их в соответствие, используя JSON.stringify().Но это для другой истории;)

1 голос
/ 29 марта 2019

Это объект accumulator. Можно сказать, что это начальное значение, поэтому при выполнении функции обратного вызова начальным значением будет пустой объект.

Итак, в приведенном ниже примере изначально он передает объект с ключом e

var a = ["a", "b", "b", "c", "a", "b", "d"];

var map = a.reduce(function(obj, b) {
  console.log(obj)
  obj[b] = ++obj[b] || 1;
  return obj;
}, {e:'test'});

console.log(map)
...