2015-04-13 5 views
2

Новое в Javascript - Я пытаюсь переписать forEach и фильтровать, чтобы понять их. Я хотел бы иметь возможность использовать фильтр, чтобы передать что-то вроде {«hello»: 4, «world»: 2, «hi»: 1} и иметь возможность фильтровать по числу.Перезапись Фильтр Javascript/forEach

Вот мой Foreach:

function myForEach(collection, callback) { 

     if (Array.isArray(collection)) { 
     for (var i = 0; i < collection.length; i++) { 
      callback(collection[i]); 
     } 
     } 
     else { 
     for (var key in collection) { 
      callback(collection[key]); 
     } 
     } 
    } 

Вот фильтр:

function filterWithForEach (collection, predicate) { 
    if (Array.isArray(collection)) { 
    var newArray = []; 
    myForEach(collection, function (element) { 
     if (predicate(element)) { 
     newArray.push(element); 
     } 
    }); 
    return newArray; 
    } 
    else { 
    var newCollection = {}; 
    myForEach(collection, function (element) { 
     if (predicate(element)) { 
     newCollection[element] = element; //here's where I think it's wrong 
     } 
    }); 
    return newCollection; 
    } 
} 

Я знаю, что проблема с тем, как я их назначение, потому что, когда я проверить это я получаю эти выходы:

console.log(filterWithForEach([1,2,3,4,5], function(num) { 
    return num > 2; 
})); // works fine 
console.log(filterWithForEach(aList, function(item) { 
    return item > 3; 
})); // provides {4: 4}.. 
+0

Почему вы все коллекции в объекте, в фильтре? 'filter' должен возвращать массив. – thefourtheye

+2

Ни JavaScript 'forEach', ни' filter' не делает то, что вы делаете в случае объекта, который не является массивом (и не ограничивает себя массивами, просто вещи, которые похожи на массив *). Если вы хотите точно знать, что они делают, [spec достаточно ясен] (http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18). Части ваших функций, которые обрабатывают массивы, являются разумно нацеленными, хотя есть несколько деталей, которые немного отличаются друг от друга. Вероятно, самое существенное различие заключается в том, что версия JavaScript не вызывает обратный вызов для записей, которые не существуют. –

+0

Вы хотите только знать значение или вам нужно знать ключ тоже? – Kushal

ответ

1

Если вы ищете объект для возврата, то так оно и должно быть.

function myForEach(collection, callback) { 

     if (Array.isArray(collection)) { 
     for (var i = 0; i < collection.length; i++) { 
      callback(collection[i]); 
     } 
     } 
     else { 
     for (var key in collection) { 
      callback(collection[key], key); 
     } 
     } 
    } 

Вот фильтр:

function filterWithForEach (collection, predicate) { 
    if (Array.isArray(collection)) { 
    var newArray = []; 
    myForEach(collection, function (element) { 
     if (predicate(element)) { 
     newArray.push(element); 
     } 
    }); 
    return newArray; 
    } 
    else { 
    var newCollection = {}; 
    myForEach(collection, function (element,key) { 
     if (predicate(element)) { 
     newCollection[key] = element;   } 
    }); 
    return newCollection; 
    } 
} 
+0

@Jessica: Обратите внимание, что ни одна из них не ведет себя как JavaScript 'forEach' /' filter'. Если смысл понять их, писать что-то, что ведет себя по-разному, не имеет смысла. –

1

Если вы хотите знать, что они делают, the spec is fairly clear и могут быть довольно разумно превращены в Jav код (на самом деле это done on MDN).

Некоторые различия между вашими и в JavaScript:

  1. в JavaScript forEach и filterсделать не использование for-in, что является принципиальной разницы между вашими и в JavaScript. Они просто работают с индексами объектов и массивов, ожидая, что объект будет массив- (например, имеют length и свойства с такими ключами, как "0", "1" и т. Д. [И да, все ключи являются строками, ключи в стандартных массивах, которые вообще не являются массивами).

  2. Версия JavaScript не вызывает обратный вызов для записей, которые не существуют (например, в случае разреженных массивов). Чтобы добавить это к вашему, вы должны добавить hasOwnProperty(index) на каком-то этапе.

  3. Версия JavaScript содержит больше аргументов для обратных вызовов.

  4. Версия JavaScript позволяет указать значение, которое должно использоваться как this при вызове обратных вызовов.

  5. Версия JavaScript занимает длину перед запуском, поэтому, если коллекция изменена, используется старая длина. В зависимости от того, где сделаны изменения, записи могут быть пропущены.

Так, например, ваш взгляд на forEach может выглядеть следующим образом:

function myForEach(collection, callback, thisArg) { 
    var l = +collection.length; 
    for (var i = 0; i < l; i++) { 
     if (collection.hasOwnProperty(i)) { 
      callback.call(thisArg, collection[i], i, collection); 
     } 
    } 
} 

Опять же, это не (удаленно) точное выполнение алгоритма в спецификации, просто небольшая модификация для вас, чтобы рассмотреть конкретные пункты, которые я поднял выше.

+0

Большое спасибо за этот ответ! Настолько полезно получить такую ​​информацию. Я буду читать дальше в пункте 4. Еще раз спасибо :) –

Смежные вопросы