Фильтр массива возвращает странные результаты

В связи с этим вопросом, я хотел попробовать это

var arr = [0,1,2,true,4,{"abc":123},6,7,{"def":456},9,[10]];
arr.filter(Object.hasOwnProperty,"abc");//outputs [0, 1, 2]
arr.filter(Object.hasOwnProperty,"2222222") //[0, 1, 2, 4, 6]

Кто-нибудь знает, почему фильтр возвращает эти значения? Спецификация фильтра и документ MDN также не дают четкого представления о том, как используется второй аргумент фильтра.

2 ответа

Решение

Второй аргумент Array.prototype.filter это значение, которое будет установлено как this к функции, которая передается в качестве первого аргумента.

Таким образом, ваш код в конечном итоге выглядит примерно так:

arr.filter(function(v, i, a) {
    return Object.hasOwnProperty.call("222", v, i, a);
});

Так что это в основном проверяет, если "222" Строка имеет свойства, которые вы перечисляете в массиве.

Из этого становится понятно, почему свойства 0, 1 а также 2 найдены - так как это индексы символов в "222" строка, и, скажем, 9 или же {"abc":123} нет - с "222" Строка не имеет таких свойств.

Это та же история с более длинной строкой, которая также включает в себя свойства 4 а также 6 только потому что это дольше.

Некоторые примеры:

Object.hasOwnProperty.call("222", 1); // true, because `"222"[1]` is there
Object.hasOwnProperty.call("222", 'foo'); // false, because `"222"['foo']` is not there

Это кристально ясно из спецификации

Array.prototype.filter ( callbackfn [ , thisArg ] ),

ЕслиthisArg параметр предоставляется, он будет использоваться как this значение для каждого вызова callbackfn,

Так:

var arr = [0,1,2,true,4,{"abc":123},6,7,{"def":456},9,[10]];
arr.filter(Object.hasOwnProperty,"2222222");

переводит на эти вызовы, в последовательности

"2222222".hasOwnProperty(0);             // true     -> 0
"2222222".hasOwnProperty(1);             // true     -> 1
"2222222".hasOwnProperty(2);             // true     -> 2
"2222222".hasOwnProperty(true);          // false    -> 
"2222222".hasOwnProperty(4);             // true     -> 4
"2222222".hasOwnProperty({"abc":123});   // false    -> 
"2222222".hasOwnProperty(6);             // true     -> 6
"2222222".hasOwnProperty(7);             // false    -> 
"2222222".hasOwnProperty({"def":456});   // false    -> 
"2222222".hasOwnProperty(9);             // false    -> 
"2222222".hasOwnProperty([10]);          // false    -> 
                                         // filter() => [0,1,2,4,6]

Строки, где это говорит true потому что строки могут быть проиндексированы в одинаковые массивы, поэтому строка с двумя символами имеет индексы 0 а также 1 как собственные свойства.

Другие вопросы по тегам