map
, filter
, reduce
and spread
operator. They are effective and helpful.map
method. In general, every time you need to change the elements of an array, consider this option. const numbers = [1, 2, 3, 4] const numbersPlusOne = numbers.map(n => n + 1) console.log(numbersPlusOne) // [2, 3, 4, 5]
const allActivities = [ { title: 'My activity', coordinates: [50.123, 3.291] }, { title: 'Another activity', coordinates: [1.238, 4.292] } ] const allCoordinates = allActivities.map(activity => activity.coordinates) console.log(allCoordinates) // [[50.123, 3.291], [1.238, 4.292]]
map
, filter
takes as its only parameter a function that is called on each element of the array. This function should return a boolean value:true
if you want to keep the element in an array;false
- if you do not want to save it. const numbers = [1, 2, 3, 4, 5, 6] const oddNumbers = numbers.filter(n => n % 2 !== 0) console.log(oddNumbers) // [1, 3, 5]
const participants = [ { id: 'a3f47', username: 'john' }, { id: 'fek28', username: 'mary' }, { id: 'n3j44', username: 'sam' }, ] function removeParticipant(participants, id) { return participants.filter(participant => participant.id !== id) } console.log(removeParticipant(participants, 'a3f47')) // [{ id: 'fek28', username: 'mary' }, { id: 'n3j44', username: 'sam' }];
reduce
method takes an array of values and combines them into one value. It takes two parameters, a callback function (which is a gearbox ) and an optional initial value (which is the first element of the array by default). The gearbox itself takes four parameters:reduce
method was called.reduce
. const numbers = [37, 12, 28, 4, 9] const total = numbers.reduce((total, n) => total + n) console.log(total) // 90
reduce
method is so functional that you can use it to build a variety of array methods like map
or filter
. const map = (arr, fn) => { return arr.reduce((mappedArr, element) => { return [...mappedArr, fn(element)] }, []) } console.log(map([1, 2, 3, 4], n => n + 1)) // [2, 3, 4, 5] const filter = (arr, fn) => { return arr.reduce((filteredArr, element) => { return fn(element) ? [...filteredArr] : [...filteredArr, element] }, []) } console.log(filter([1, 2, 3, 4, 5, 6], n => n % 2 === 0)) // [1, 3, 5]
[]
to the reduce
method, the battery. For map
we run a function, the result of which is added to the end of the battery using the spread operator (we’ll talk about it below, do not worry). For filter
do almost the same thing, only we run the filter function on the element. If it is true, we return the previous array. Otherwise, add the element to the end of the array.[1, 2, 3, [4, [[[5, [6, 7]]]], 8]]
to [1, 2, 3, 4, 5, 6, 7, 8]
. function flatDeep(arr) { return arr.reduce((flattenArray, element) => { return Array.isArray(element) ? [...flattenArray, ...flatDeep(element)] : [...flattenArray, element] }, []) } console.log(flatDeep([1, 2, 3, [4, [[[5, [6, 7]]]], 8]])) // [1, 2, 3, 4, 5, 6, 7, 8]
map
, except that we use recursion here. I will not dwell on recursion in detail, because it goes beyond our theme, but if you want to learn more, go to this great resource . const numbers = [1, 2, 3] const numbersCopy = [...numbers] console.log(numbersCopy) // [1, 2, 3] const otherNumbers = [4, 5, 6] const numbersConcatenated = [...numbers, ...otherNumbers] console.log(numbersConcatenated) // [1, 2, 3, 4, 5, 6]
const arr = ['foo', 42, { name: 'Thomas' }] let copy = [...arr] copy[0] = 'bar' console.log(arr) // No mutations: ["foo", 42, { name: "Thomas" }] console.log(copy) // ["bar", 42, { name: "Thomas" }] copy[2].name = 'Hello' console.log(arr) // /!\ MUTATION ["foo", 42, { name: "Hello" }] console.log(copy) // ["bar", 42, { name: "Hello" }]
indexOf
to find out if there is an element in an array or not? A terrible way to check, right?includes
method does the checking for us. Specify the parameter for includes, and it will search the item by array. const sports = ['football', 'archery', 'judo'] const hasFootball = sports.includes('football') console.log(hasFootball) // true
const numbers = [1, 2, 3] const otherNumbers = [4, 5, 6] const numbersConcatenated = numbers.concat(otherNumbers) console.log(numbersConcatenated) // [1, 2, 3, 4, 5, 6] // You can merge as many arrays as you want function concatAll(arr, ...arrays) { return arr.concat(...arrays) } console.log(concatAll([1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12])) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
forEach
method. It takes a function as a parameter, which, in turn, also takes three parameters: the current value, the index, and the array. const numbers = [1, 2, 3, 4, 5] numbers.forEach(console.log) // 1 0 [ 1, 2, 3 ] // 2 1 [ 1, 2, 3 ] // 3 2 [ 1, 2, 3 ]
indexOf
often check the presence of an element in the array. Honestly, now I use it infrequently. const sports = ['football', 'archery', 'judo'] const judoIndex = sports.indexOf('judo') console.log(judoIndex) // 2
find
method is similar to filter
. You need to provide it with a function that tests each element of the array. However, find
stops testing elements as soon as it finds one that passed the test. This is not a filter
that iterates over the entire array, regardless of the circumstances. const users = [ { id: 'af35', name: 'john' }, { id: '6gbe', name: 'mary' }, { id: '932j', name: 'gary' }, ] const user = users.find(user => user.id === '6gbe') console.log(user) // { id: '6gbe', name: 'mary' }
filter
method when you want to filter the entire array, and the find
method when you are sure that you are looking for a unique element in the array.find
, but it returns the index of the first element found instead of the element itself. const users = [ { id: 'af35', name: 'john' }, { id: '6gbe', name: 'mary' }, { id: '932j', name: 'gary' }, ] const user = users.findIndex(user => user.id === '6gbe') console.log(user) // 1
findIndex
and indexOf
are the same thing. Not really. The first parameter of indexOf
is a primitive value (boolean, number, string, undefined value, or character), while the first parameter findIndex
is a callback function.indexOf
. If you have more complex elements, such as objects, use findIndex
.slice
method. But be careful: as the spread operator, slice
returns a shallow copy . const numbers = [1, 2, 3, 4, 5] const copy = numbers.slice()
slice
method. // The "traditional way" to do it: // Determine the number of messages to take and use a for loop const nbMessages = messages.length < 5 ? messages.length : 5 let messagesToShow = [] for (let i = 0; i < nbMessages; i++) { messagesToShow.push(posts[i]) } // Even if "arr" has less than 5 elements, // slice will return an entire shallow copy of the original array const messagesToShow = messages.slice(0, 5)
some
. Like map
, filter
or find
, the some
method takes a callback function as the only parameter, and then returns true
if at least one element passes the test, and false
if not.some
suitable for working with permissions. const users = [ { id: 'fe34', permissions: ['read', 'write'], }, { id: 'a198', permissions: [], }, { id: '18aa', permissions: ['delete', 'read', 'write'], } ] const hasDeletePermission = users.some(user => user.permissions.includes('delete') ) console.log(hasDeletePermission) // true
some
, except that it checks that each element (and not one ) matches the condition. const users = [ { id: 'fe34', permissions: ['read', 'write'], }, { id: 'a198', permissions: [], }, { id: '18aa', permissions: ['delete', 'read', 'write'], } ] const hasAllReadPermission = users.every(user => user.permissions.includes('read') ) console.log(hasAllReadPermission) // false
flat
creates a new array, connecting all the elements of the nested array. It takes one parameter — a number that indicates how much you want to reduce the dimension of the array. const numbers = [1, 2, [3, 4, [5, [6, 7]], [[[[8]]]]]] const numbersflattenOnce = numbers.flat() console.log(numbersflattenOnce) // [1, 2, 3, 4, Array[2], Array[1]] const numbersflattenTwice = numbers.flat(2) console.log(numbersflattenTwice) // [1, 2, 3, 4, 5, Array[2], Array[1]] const numbersFlattenInfinity = numbers.flat(Infinity) console.log(numbersFlattenInfinity) // [1, 2, 3, 4, 5, 6, 7, 8]
const sentences = [ 'This is a sentence', 'This is another sentence', "I can't find any original phrases", ] const allWords = sentences.flatMap(sentence => sentence.split(' ')) console.log(allWords) // ["This", "is", "a", "sentence", "This", "is", "another", "sentence", "I", "can't", "find", "any", "original", "phrases"]
map
method and dividing all sentences into words, and then shortening the array, you can immediately use flatMap
.reduce
function (this does not apply to flatMap
, I just want to show you another example of using the reduce
method). const wordsCount = allWords.reduce((count, word) => { count[word] = count[word] ? count[word] + 1 : 1 return count }, {}) console.log(wordsCount) // { This: 2, is: 2, a: 1, sentence: 2, another: 1, I: 1, "can't": 1, find: 1, any: 1, original: 1, phrases: 1, }
flatMap
method flatMap
also often used in reactive programming. An example you can see here .join
method is what you need. It allows you to create a new line, connecting all the elements of the array, separated by the provided separator.join
you can visually display all participants in the activity. const participants = ['john', 'mary', 'gary'] const participantsFormatted = participants.join(', ') console.log(participantsFormatted) // john, mary, gary
const potentialParticipants = [ { id: 'k38i', name: 'john', age: 17 }, { id: 'baf3', name: 'mary', age: 13 }, { id: 'a111', name: 'gary', age: 24 }, { id: 'fx34', name: 'emma', age: 34 }, ] const participantsFormatted = potentialParticipants .filter(user => user.age > 18) .map(user => user.name) .join(', ') console.log(participantsFormatted) // gary, emma
const nodes = document.querySelectorAll('.todo-item') // this is an instance of NodeList const todoItems = Array.from(nodes) // now, you can use map, filter, etc. as you're workin with an array!
forEach
method. todoItems.forEach(item => { item.addEventListener('click', function() { alert(`You clicked on ${item.innerHTML}`) }) })
const arr = [1, 2, 3, 4, 5] const copy = [...arr] // or arr.slice()
sort
changes the original array. In fact, it sorts the elements of the array in place. The default sort method transforms all elements into strings and sorts them alphabetically. const names = ['john', 'mary', 'gary', 'anna'] names.sort() console.log(names) // ['anna', 'gary', 'john', 'mary']
sort
method when working with an array of numbers will not give you the desired result. const numbers = [23, 12, 17, 187, 3, 90] numbers.sort() console.log(numbers) // [12, 17, 187, 23, 3, 90]
sort
method takes one function - the comparison function . It takes two parameters: the first element (
) and the second element for comparison ( b
). A comparison between these two elements requires the return of a digit:a
sorted before b
;b
sorted before a
; const numbers = [23, 12, 17, 187, 3, 90] numbers.sort((a, b) => a - b) console.log(numbers) // [3, 12, 17, 23, 90, 187]
const posts = [ { title: 'Create a Discord bot under 15 minutes', date: new Date(2018, 11, 26), }, { title: 'How to get better at writing CSS', date: new Date(2018, 06, 17) }, { title: 'JavaScript arrays', date: new Date() }, ] posts.sort((a, b) => a.date - b.date) // Substracting two dates returns the difference in millisecond between them console.log(posts) // [ { title: 'How to get better at writing CSS', // date: 2018-07-17T00:00:00.000Z }, // { title: 'Create a Discord bot under 15 minutes', // date: 2018-12-26T00:00:00.000Z }, // { title: 'Learn Javascript arrays the functional way', // date: 2019-03-16T10:31:00.208Z } ]
fill
method changes or fills all elements of an array from the initial index to the final one with the specified value. An example of excellent use of fill
is to fill a new array with initial data. // Normally I would have called a function that generates ids and random names but let's not bother with that here. function fakeUser() { return { id: 'fe38', name: 'thomas', } } const posts = Array(3).fill(fakeUser()) console.log(posts) // [{ id: "fe38", name: "thomas" }, { id: "fe38", name: "thomas" }, { id: "fe38", name: "thomas" }]
const numbers = [1, 2, 3, 4, 5] numbers.reverse() console.log(numbers) // [5, 4, 3, 2, 1]
const messages = ['Hello', 'Hey', 'How are you?', "I'm fine"] const lastMessage = messages.pop() console.log(messages) // ['Hello', 'Hey', 'How are you?'] console.log(lastMessage) // I'm fine
const todoItems = [1, 2, 3, 4, 5] const itemsIncremented = [] for (let i = 0; i < items.length; i++) { itemsIncremented.push(items[i] + 1) } console.log(itemsIncremented) // [2, 3, 4, 5, 6] const todos = ['Write an article', 'Proofreading'] todos.push('Publish the article') console.log(todos) // ['Write an article', 'Proofreading', 'Publish the article']
itemsIncremented
method, there are suitable for this and already familiar to us map
, filter
or reduce
. For example, we can take a map
to do this. const itemsIncremented = todoItems.map(x => x + 1)
push
when you need to add a new element, then the spread operator comes in handy. const todos = ['Write an article', 'Proofreading'] console.log([...todos, 'Publish the article'])
splice
often referenced to remove an element on a specific index. You can do the same with the filter
method. const months = ['January', 'February', 'March', 'April', ' May'] // With splice months.splice(2, 1) // remove one element at index 2 console.log(months) // ['January', 'February', 'April', 'May'] // Without splice const monthsFiltered = months.filter((month, i) => i !== 3) console.log(monthsFiltered) // ['January', 'February', 'April', 'May']
slice
. const months = ['January', 'February', 'March', 'April', ' May'] // With splice months.splice(1, 3) // remove thirds element starting at index 1 console.log(months) // ['January', 'February', 'April', 'May'] // Without splice const monthsFiltered = [...months.slice(0, 1), ...months.slice(4)] console.log(monthsFiltered) // ['January', 'February', 'April', 'May']
shift
method removes the first element of the array and returns it. To do this in the style of functional programming, you can use the spread or rest operator. const numbers = [1, 2, 3, 4, 5] // With shift const firstNumber = numbers.shift() console.log(firstNumber) // 1 console.log(numbers) // [2, 3, 4, 5] // Without shift const [firstNumber, ...numbersWithoutOne] = numbers console.log(firstNumber) // 1 console.log(numbersWithoutOne) // [2, 3, 4, 5]
shift
, you can do this with the spread operator. const numbers = [3, 4, 5] // With unshift numbers.unshift(1, 2) console.log(numbers) // [1, 2, 3, 4, 5] // Without unshift const newNumbers = [1, 2, ...numbers] console.log(newNumbers) // [1, 2, 3, 4, 5]
map
, filter
, reduce
and the spread operator - these are important tools for any developer.slice
, some
, flatMap
, . . .slice
spread . — .Source: https://habr.com/ru/post/446902/
All Articles