TypeError: this.reduce не является функцией

После добавления метода в прототип Array прерывается какой-то другой, не связанный с ним скрипт.

  • [Opera] Необработанная ошибка: this.reduce не является функцией
  • [Firefox] TypeError: this.reduce не является функцией

Сам метод работает ([1,2,3].xintsum() выводит 6 как положено).

// adding a function to the Array prototype
Array.prototype.xintsum = function() { return this.reduce(function(old, add) {return old + add;}, 0); };

// accessing the array in a way that worked before
$(document).ready(function (){
  var some_array = [];
  for (head_n in some_array) {
    var v = some_array[head_n];
    $('<th></th>').text(v);
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


person Community    schedule 14.01.2014    source источник
comment
На что должен ссылаться this? Вы уверены, что это array?   -  person Sterling Archer    schedule 14.01.2014
comment
В Chrome я получаю Uncaught TypeError: Object #<HTMLTableCellElement> has no method 'reduce'.   -  person Rocket Hazmat    schedule 14.01.2014


Ответы (3)


Это происходит потому, что вы используете for..in в массиве. Вы не должны этого делать.

Когда вы добавили Array.prototype.xintsum, вы добавили свойство xintsum в каждый массив. Итак, произошло то, что ваш цикл for повторил это свойство вашего массива.

Значение этого свойства является функцией. Когда вы передаете функцию .text(), jQuery вызывает ее следующим образом:

v.call(ele, index text);

Он устанавливает this для элемента. И хорошо, у DOMElements нет .reduce функций.

Вам нужно зациклиться следующим образом:

for(var i = 0; i < some_array.length; i++){
    var v = some_array[i];
}
person Rocket Hazmat    schedule 14.01.2014
comment
Или используйте some_array.forEach() ;) - person Scimonster; 14.01.2014
comment
@Scimonster: Да, это тоже сработает :-) - person Rocket Hazmat; 14.01.2014
comment
Или вы можете использовать for...of из ES6. Этот цикл решает проблему зацикливания свойств, не являющихся элементами. - person prgmrDev; 06.12.2017

v() вызывается в контексте элемента <th>, а не массива. Следовательно, у <th> нет метода reduce(). Это связано с тем, что for ... in перебирает нечисловые свойства точно так же, как числовые свойства. Вместо этого я бы рекомендовал использовать some_array['head'].forEach().

person Scimonster    schedule 14.01.2014
comment
Я считаю, что проблема в том, что вы используете «для входа» в массиве. Из-за этого вы получаете прототипы в чеке... for in... выполните цикл for, и ваша проблема должна быть решена. Вы не должны использовать «для» для массивов, то есть для ассоциативных массивов/хэшей. использовать for для массива. Думаю, это ваша проблема. - person james emanon; 14.01.2014
comment
Пожалуйста. Кстати, журналы консоли часто намного проще, чем предупреждения, потому что они не блокируют и обычно позволяют вам более тщательно проверять объект. - person Scimonster; 14.01.2014

Этот код:

var v = some_array[head_n];
$('<th></th>').text(v);

когда он доходит до xintsum, это то же самое:

$('<th></th>').text(function() { 
    return this.reduce(function(old, add) {
        return old + add;
    }, 0); 
});

Когда функция передается в text, функция вызывается один раз для каждого элемента, содержащегося в объекте jquery, для которого она вызывается. Для каждого вызова this относится к этому элементу dom. В данном случае созданный вами файл th. Таким образом, сообщение об ошибке сообщает вам, что th не имеет такой функции.

person James Montagne    schedule 14.01.2014