Фильтр массива возвращает странные результаты
В связи с этим вопросом, я хотел попробовать это
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
как собственные свойства.