Nowadays, all kinds of frameworks and tools “run amok”, everywhere in the principle and source code, more cross-end technology needs us to explore, but if the basic skills are not good, learn what is half the effort, the effect is very bad, take time at the same time to blow confidence. This article, the first (nine) in the series of “light talk front end” planned by me, aims to share the native JavaScript knowledge with you systematically and logically, helping you to easily understand the knowledge system and better understand and memorize. I will do my best to live up to expectations.
In the last article we talked about objects, which are collections of properties and methods that represent individuals that contain some information or capability.
In this article, we’ll talk about another kind of aggregate — arrays, which represent a series of homogeneous data.
Arrays are also ubiquitous, used whenever you need to transfer or display more than one of the same kind of data.
Let’s start with the definition.
To define an array
An array is a group of data that looks like this:
[1, 2, 3, 4]Copy the code
In JavaScript, array elements can be of any type, but it is often more common and practical to have a set of data of the same type.
Arrays can be defined in the following ways:
- literal
- Array() constructor
- Using… on iterables Extension operator
- Factory methods array.of () and array.from ()
literal
The simplest and most intuitive, and one of the most commonly used.
Let arr = [1, 2, 3]Copy the code
There are two things to watch out for:
Let arr = [1, 3] // Access arr[1] will be undefined let arr = [,,] // array length will be 2Copy the code
Many times, we will initialize an empty array and then add elements to it based on business logic, as described in the “Methods” section below.
Array() constructor
Constructors are one of the most logical ways to create arrays. It looks like this.
Let arr1 = new Array(1,2,3,4) // 4] let arr2 = new Array(1) // [ <1 empty item> ] let arr3 = new Array('1') // [ '1' ]Copy the code
There is a mystery in the seemingly simple form:
- When a constructor takes multiple arguments, each item is created as an element.
- When there is only one number, it represents the length of the array, the element is not filled, and the access is undefined.
- With only one non-number, a single element array is created.
Extend iterables
Iteration is an old concept in programming, meaning that all elements in a collection can be accessed using some method, but in JavaScript, iterable is a new concept introduced after ES6, iterable.
What types are iterable? Examples include arrays, maps, sets, array-like objects — Arguments, DOM NodeList objects, Generator objects, strings, etc.
Let’s try it one by one.
string
Just look at the code.
let str1 = 'hello world'
[...str1] // ["h", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d"]
Copy the code
When we talked about strings in the previous section, we talked about a split() method that creates an array of characters delimiting a string. Here, we can use the extension operator directly to convert the string, but this “shredding” effect is rarely used.
Map
A Map is a new object introduced in ES6 that holds key-value pairs and can remember the original insertion order of keys.
Hey, save key-value pairs, that’s not our familiar Object, right?
It is true that before Map, many similar requirements were implemented using Object, but there are several important differences:
- By default, Map contains no keys, only explicitly inserted keys, while Object has stereotypes, which contain keys on the stereotypes.
- The Map key can be any value, and the Object key must be a String or Symbol.
- Keys in Map are ordered, while keys in Object are out of order.
- The number of Map key-value pairs can be obtained using the size attribute. Object can only be calculated manually.
Create a Map for a quick overview:
let map1 = new Map();
map1.set('a',1)
map1.set('b',2) // {"a" => 1, "b" => 2}
map1.size // 2
map1.get('a') // 1
map1.delete('a') //{ 'b' => 2 }
Copy the code
The difference between A Map Object and an Object can be seen more clearly from the above Map Object manipulation and access to elements.
How do you convert an array with a Map? You just use the extension operator.
let arr6 = [...map1] //[ [ 'a', 1 ], [ 'b', 2 ] ]
Copy the code
You can easily convert a map into an array using the extension operator, but it’s not an array of objects. It’s a two-dimensional array that takes the keys and values of the original object, so you need to be careful.
Set
Like A Map, a Set is a new collection tool provided by ES6. Like an array, it contains a Set of data, except that it does not allow the addition of duplicate data. Look at the code:
let set1 = new Set();
set1.add(1)
set1.add(2) // { 1, 2 }
set1.add(2) // { 1, 2 }
set1.size //2
set1.delete(1) //{2}
let arr5 = [...set1] //[ 1, 2 ]
Copy the code
In the above code we create a Set of two elements, and then easily convert it to an array using the extension operator as well.
An array of class
An array is a form of data that looks like an array but does not have all the features of an array. The more common ones are arguments objects and DOM NodeList objects.
Arguments can be used to get the function argument list.
Function func(){console.log(arguments) // [1, 2,3,4,5, callee: ƒ, Symbol(Symbol. Iterator): ƒ]} func(Copy the code
NodeList is what we get when we use JS to get DOM nodes, for example, two DOM elements of class ‘item’ on the page.
<div class="item"></div>
<div class="item"></div>
let itemDom = document.getElementsByClassName('item')
// HTMLCollection:[div.item,div.item]
Copy the code
As shown above, using getElementsByClassName gives you an HTMLCollection that contains two divs with the class name Item.
They all look like arrays, but they don’t have any Array capabilities other than the ability to access the Length attribute. If you want to take advantage of those capabilities, you need to transform them, which was usually done with Array’s prototypical methods prior to ES6.
function func(){
let arsArray = Array.prototype.slice.call(arguments)
// [1, 2, 3, 4, 5]
}
Copy the code
After ES6, it’s a little cleaner
function func(){
let arsArray = [...arguments]
// [1, 2, 3, 4, 5]
}
Copy the code
Array) of () and Array) from ()
Array.from() works like the extension operator, but differently.
Array.of() — Creates a new Array instance with a variable number. Array.from() — Creates a new, shallow-copy Array instance from an array-like or iterable.
Let’s just take one example.
function func(){
let arsArray = Array.from(arguments)
console.log(arsArray) // [1, 2, 3, 4, 5, callee: ƒ, Symbol(Symbol.iterator): ƒ]
}
func(1,2,3,4,5)
Copy the code
Array.from() converts the function’s arguments to a real Array.
Array.of() is more like Array(), for example:
Array.of(1); // [1]
Array.of(1, 2, 3); // [1, 2, 3]
Array.of(7) //[7]
Copy the code
One notable difference from Array() is that when a single number is passed in, it is treated as a single element, not as a number of elements.
Okay, so that’s the end of creating arrays.
Create an array is a first step, we may be created from scratch, or class array is converted to an array, or, other types will be converted to an array (for example, a string), the purpose of these operations, is the method of using arrays have mostly serve for specific target, next, let’s see what are the powerful method of array and how to use.
Common array methods and applications
Array methods are many and versatile, and they are the key to their power.
If you are a beginner, don’t expect to be able to remember by looking at it. In the past, I read the array chapter of “Elevation” 3 several times and did not remember it. However, it does not mean that there is no method to help memory, and combine it with the actual application scenarios, you can better remember.
We count them one by one.
— array.isarray ()
Sometimes, we need to check whether the data we get is an array or not, otherwise we may get an error in the method call. In the past, it was not very convenient to check the array, so we used the following methods:
- instanceof
Determine if the left side of the operator is an instanceof the right type, i.e., an instanceof b. So let’s just set b to Array and return a Boolean.
- constructor
Constructor == Array (array_constructor); constructor == Array (array_constructor);
- Object.prototype.toString.call()
This method is designed to convert the instance type to a string and then print it, or if the instance is an Array type, print ‘[Object Array]’ to make a determination. Because the first two methods may have some uncertainties, this method, once considered to be the most accurate and reliable method for judging other reference types, is also the same.
The emergence of ES6 provides a new judgment method — isArray(). Only array.isarray (obj) is needed to determine whether OBj is an Array, which provides great convenience.
Add and remove — push()/pop(), unshift()/shift()
Once an array is created, it may or may not have elements. These two sets of methods are often used to dynamically add or remove elements from an array, but they can only operate from both ends of the array in a limited way, which is sufficient for suitable scenarios.
What are the appropriate scenarios? Just the elements that meet the criteria, no order, no strings attached, can be handled in this way.
const arr = [],ele; If (ele > 1){arr.push(ele)}Copy the code
The same goes for the other pair.
Add or remove — splice()/slice()
Since the above method has limitations, this group is more flexible. Its flexibility is reflected in the fact that it can add, delete, and replace at any position, depending on the situation of the parameter passing.
Parameter format: splice(index, NUMs, Item1,….. ,itemX)
They represent:
Index — Start position
Nums — Number of free positions
item1,….. ItemX — what elements to add from the empty space
The first two parameters are mandatory, and the third parameter is optional. It can be concluded that:
If the second parameter is 0, the element is not deleted. If the third parameter has a value, the element is added to the specified position.
If the second argument is a non-zero positive integer, the specified number of elements is deleted. If the third argument has data, it is filled to the position of the deleted element to replace the element.
So what is slice(), and how is it different?
Slice looks a lot like Splice, with only one letter missing, but uses two major differences:
Slice takes two arguments, begin and end, that determine which portion of the source array to truncate. The truncated portion includes BEGIN, but not end
Slice returns a new array that is a shallow copy of the source array. The source array is unaffected
So, the use of these two methods can be summarized as: Slice if you want to do something based on the source array, but do not change the source array, otherwise splice.
IndexOf a specific element — indexOf()/findIndex()
In the previous method, we mentioned “element” and “location”. In many cases, the location of an element is not known, and in order to obtain it dynamically, it is useful to find the index.
The results obtained by these two methods are similar, but there are differences in usage.
- indexOf(searchElement[, fromIndex])
The indexOf() method requires passing in the specific lookup element and, optionally, the starting index.
const nums = [1, 2, 3, 4, 5]; nums.indexOf(3); / / 2Copy the code
- The findIndex() method passes in a callback function
The function supports three optional arguments: element, index, and array itself. Usually, using the first two or even one parameter is enough. Something like this:
const nums = [1, 2, 3, 4, 5];
let targetIndex = nums.findIndex(target => target == 3) //2
Copy the code
Note in particular that sometimes the results are different from what is expected, i.e. when there are multiple target elements in the array, they all return only the location of the first target element.
const nums = [1, 2, 3, 3, 5];
nums.indexOf(3); //2
let targetIndex = nums.findIndex(target => target == 3) //2
Copy the code
This is normal; if an exception, such as an element that does not exist, returns -1 in both cases.
Find elements — includesOf()/find()
The first set of methods, you can find out where the element is in the array, and of course, you can tell if the element is in the array by returning -1, and this set of methods, you can just find out if the element is in the array.
- IncludesOf () — returns a Boolean value
const nums = [1, 2, 3, 3, 5];
nums.includes(1) //true
nums.includes(8) //false
Copy the code
- Find ()- Returns the target value itself
const nums = [1, 2, 3, 3, 5];
nums.includes(1) //1
nums.includes(8) //undefined
Copy the code
Fill, fill ()
You can create an empty array and add to it. You can also create ready-made arrays using literals. You can also add, delete, or change arrays using splice.
Look at the usage.
const arr = new Array()
arr.fill(1) //[]
Copy the code
Oh oh ~ seems to turn over the car, said to fill, why is the empty array?
Wait, fill() doesn’t work that way. It works if there are already a certain number of elements in the array. Such as:
It can go like this:
Const arr = new Array(1,2,3,4) arr. Fill (5) // [5, 5, 5, 5]Copy the code
You can do that
const arr = new Array(4)
arr.fill(5) // [ 5, 5, 5, 5 ]
Copy the code
From this, we can get a fast way to create a certain number of non-empty arrays.
Arr. Fill (value[, start[, end]])
Deja vu, it also takes two position parameters, a start position and an end position, and when we didn’t pass them above, they default to start to end, and we can experiment with that.
Const arr = [6] arr. The fill (5, 4-trichlorobenzene) / / [1, 2, 5, 5, 5, 6]Copy the code
However, a common mistake with fill() is to fill the same reference when the element is a reference type, such as initializing a list of items.
Const goodsList = {name:' jewelry ', price:10, weight:'20'} const goodsList = new Array(8) goodsList. Fill (goods)Copy the code
The item list data would look like this:
[{name: 'jewelry ', price: 10, weight: '20'}, {name:' jewelry ', price: 10, weight: '20'}, {name: 'jewelry ', price: 10, weight: '20'}, {name:' jewelry ', price: 10, weight: '20'}, {name: 'jewelry ', price: 10, weight: '20'}, '20'}, {name: 'jewelry, price: 10, weight:' 20 '}, {name: 'jewelry, price: 10, weight:' 20 '}, {name: 'jewelry, price: 10, weight: '20'}, {name: 'jewelry ', price: 10, weight: '20'}, {name:' jewelry ', price: 10, weight: '20'}]Copy the code
Then we edit the first item and change the price to 8
goodsList[0].price = 8
Copy the code
Only to find that the price of each item has been changed.
[{name: 'jewelry ', price: 8, weight: '20'}, {name:' jewelry ', price: 8, weight: '20'}, {name: 'jewelry ', price: 8, weight: '20'}, {name:' jewelry ', price: 8, weight: '20'}, {name: 'jewelry ', price: 8, weight: '20'}, '20'}, {name: 'jewelry, price: 8, weight:' 20 '}, {name: 'jewelry, price: 8, weight:' 20 '}, {name: 'jewelry, price: 8, weight: '20'}, {name: 'jewelry, price: 8, weight:' 20 '}, {name: 'jewelry, price: 8, weight:' 20 '}]Copy the code
This is clearly not the desired effect.
Not only that, but arrays are also reference types, so this is also a problem when initializing two-dimensional arrays, so if there is a need to have a set of data items ready to edit/modify when the page is initialized, this is not a good way to create.
Sort – the sort ()
Sorting is a common demand, where the list is involved, there must be sorting, by time, by price, by sales, etc.
The simplest way is to sort a list of numbers.
Const numSort =,2,8,6,5,7,9,1,4 [3]. The sort () numSort / / [1, 2, 3, 4, 5, 6, 7, 8, 9]Copy the code
So simple, what is there to say?
Of course there is, and a small example that really does trick us, which is the order of numbers from smallest to largest, right? No, look again.
Let’s change the array above:
,2,8,10,6,20,5,7,9,1,4 const numSort = [3]. The sort () / / [1, 2, 10, 20, 3, 4, 5, 6, 7, 8, 9]Copy the code
Something amazing happens. Ten is less than two, right? 20 is less than 3?
Note that the sort() method actually takes a function that specifies a sort order by the return value of the function or, if the function is omitted, by the Unicode point of each character that converts the element to a string. So, if you wanted to sort the numbers by their true size, you could write it like this.
,2,8,10,6,20,5,7,9,1,4 [3]. Sort (a, b) = > (a - b)Copy the code
On what basis? Is the sorting function algorithm rule:
- If a – b is less than 0, A will be placed before B;
- If a minus b is equal to 0, the relative positions of a and B remain the same;
- If a minus b is greater than 0, B will be placed before A.
If the comparison object is a string, the method is the same, so in general, don’t be lazy, we can take full advantage of this feature and customize the rules we need.
The above is about sorting numbers or strings. In everyday applications, sorting is not always as simple as sorting an array of objects containing multiple attributes, such as price, sales volume, etc.
How to sort an array by a property.
In the same way that the goodsList, for example, sorted by price, looks like this:
goodList.sort((a,b)=>{
return (a.price - b.price)
})
Copy the code
That’s it.
Reverse: [1,2,3] becomes [3,2,1] and [‘a’,’f’,’c’] becomes [‘ c’, ‘f’,’ a’].
Merge — concat()/ extension operations
Ideally, we get an array, and it’s best to manipulate an array, but sometimes more than one source of data, possibly two or more, needs to be combined into one when presented or passed, and we use the merge method, which is traditionally concat().
Const primary = [6], middle =,8,9 [7], high = final three [10]; const grade = primary.concat(middle,high) //[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]Copy the code
But it would be a mistake to think that was all.
- Concat () can be used to merge not only arrays, but also an array and other types of values, such as numbers, strings, and so on.
Concat (7,8) // [1, 2, 3, 4, 5, 6, 7,8]Copy the code
- When concat() merges arrays, it does not change the original array, but returns a new array that contains a shallow copy of the original array.
const primary = [{a:1}],
middle = [{b:2}];
const grade = primary.concat(middle)
//[ { a: 1 }, { b: 2 } ]
primary[0].a = 2
middle[0].b = 3
// [ { a: 2 }, { b: 3 } ]
Copy the code
Reference types are always surprising, so be careful when you use them.
Of course, extension operators are still concise. The above operation only needs to do this:
const grade = [...primary,...middle,...high]
Copy the code
Return a new array — map()/filter()
What does a new array mean?
In most cases, we get the data is an array of objects, object is a collection, contains a lot of things, its own data, it is related to other data, etc., is a few less, more than dozens of, but at the time of transfer or display does not need them all with, or, we need to process on the basis of the original, At this point, you can return the processed new array on demand.
Like this:
[{name: 'jewelry ', price: 1000, weight: '20'}, {name:' phone ', price: 2000, weight: '20'},.. {name: 'computer ', price: 5000, weight: '20' } ]Copy the code
We get a list of items, but we just need to take the name out and use it, and that’s it.
Let nameList = goodsList. Map (item=>{return item.name}) [' jewelry '.' phone ',... 'computer ']Copy the code
Or, we need to discount all the goods on the basis of the original price, we can do this:
Let priceDiscountList = goodslist. map(item=>{item.price *= 0.5 return item}) [{name: 'jewelry ', price: 500, weight: '20'}, {name: 'mobile phone', price: 1000, weight: '20'},... {name: 'computer' price: 2500, weight: '20'}]Copy the code
Of course, this link in the actual project will not do so, otherwise every change will have to change the JS logic code, from the ease of use, efficiency and maintenance are unfavorable, just to illustrate the usage.
After introducing map, let’s look at filter, which literally means “filter”, it will be filtered if it meets the criteria, and it will also receive a function.
Let’s say we find the ones that cost more than 500.
Let priceLowList = goodsList. Filter (item=>{return item.price > 500}) [{name: 'phone ', price: 1000, weight: '20'},... {name: 'computer' price: 2500, weight: '20'}]Copy the code
These two methods are very common in real projects, but the only thing to notice is how they work. They both generate new arrays. Map returns array elements and fliter filters.
Iterative processing — forEach()
This method, very similar to the above two, can access each element of the array from the bottom, and then the corresponding processing, the difference is that this method is only used for iteration, like the common for loop, of course, the simplicity of the function means that there is more space to manipulate.
For example, we can achieve a map-like effect like this.
let nameList = []
goodsList.forEach(item=>{
nameList.push(item.name)
})
Copy the code
A filter-like effect can also be achieved in this way.
let priceLowList = []
goodsList.forEach(item=>{
if(item.price > 500){
priceLowList.push(item)
}
})
Copy the code
Yes, you can write any logic you want, and it’s more efficient than a for loop, and it fits more into the functional programming paradigm.
Element judgment — some()/every()
Also used to check and receive the callback function, written judgment logic, the difference is that some () is a “fit” that is true, and every () is “all” to true, only similar | | and &&. Relatively simple, do not repeat.
Application development
No matter what they learn, people are used to pursuing “knowledge” and “knowledge”, lacking in the direction of “living” to continue to dig, but often “living” with things can bring more benefits and surprises.
Let’s see how arrays can be used in more applications.
duplicate removal
When the user’s operations are large and uncertain, it is inevitable that there will be duplication. Sometimes we just need to know if a value exists, rather than multiple duplicate values, and then we need to de-duplicate the array (of course, there are other ways to ensure a single value, but the emphasis here is on de-duplication).
There are a number of ways to de-duplicate data, but the principle is similar — to ensure that the value is unique by comparing the data sets. Column three for your reference:
- includes
function unique(arr) { if (! Array.isArray(arr)) { console.log('type error! ') return } var array =[]; for(var i = 0; i < arr.length; i++) { if( ! Array.push (arr[I]); array.push(arr[I]); } } return array }Copy the code
- filter
Arr. Filter (function(item, index, arr) {return arr. Filter (function(item, index, arr) {return arr. Return arr.indexof (item, 0) === index; }); }Copy the code
- Set
function unique (arr) {
return Array.from(new Set(arr))
}
Copy the code
sum
The need for summation is not very common, but it is something to master.
- recursive
It’s easy to think about recursion without thinking about complexity.
function sum(arr) { var len = arr.length; if(len == 0){ return 0; } else if (len == 1){ return arr[0]; } else { return arr[0] + sum(arr.slice(1)); }}Copy the code
- cycle
function sum(arr) {
var s = 0;
for (var i=arr.length-1; i>=0; i--) {
s += arr[i];
}
return s;
}
Copy the code
- reduce()
I should have included this method above, but it’s more appropriate here, so let’s see what it is.
Complete parameter list:
reduce(accumulator, currentValue, index, array)
PreviousValue: the value returned by the callback of the last call or the initialValue provided (initialValue) currentValue: the element being processed index: the index of the current element array: the array for invoking reduce
If you just look at the first two terms, you can see that previousValue is the same thing as s in the loop. CurrentValue is arr[I], so the sum just looks like this:
function sum(arr) {
return arr.reduce(function(prev, curr){
return prev + curr;
});
}
Copy the code
There are many other things reduce can do, some of which can even be called “clever tricks”. I won’t cover them here for space, but I’ll talk more about them at the end of this series.
Pat down
This word is more grounded, pat flat, means the operation is uneven before, how to call uneven? Such as:
[1, 2, 3], 4, [5, [6, 7]]]Copy the code
This array has elements and arrays, and arrays and arrays, and it’s hierarchical nesting, and if we try to treat them like a one-dimensional or a two-dimensional array, obviously we’re going to make a mistake, and we’re going to have to reduce the dimension.
Before ES5, flat() was not so easy, but ES6 has a new “smell” method — flat()
How do I do that? If I want my array up here to be a two-dimensional array, I do this:
arrFlat.flat(1)
// [ 1, 2, 3, 4, 5, [ 6, 7 ] ]
Copy the code
Flat out like this:
arrFlat.flat(2)
// [ 1, 2, 3, 4, 5, 6, 7 ]
Copy the code
By default, only one layer is processed, that is, flat() is equivalent to flat(1).
“Advanced” data structures
Now when people go out for interviews, they are nervous about two things, one is “principle” and the other is “algorithm”.
Algorithms are inseparable from data structures. JavaScript native data structures are rare. The language itself only provides basic capabilities, but more complex or special-purpose structures can be derived from basic capabilities.
The tree
The above mentioned array array, in fact, the more common “tree”, is the array array, a parent node contains multiple child nodes, child nodes may also contain child nodes, become a tree.
The most common ones are administrative region tree, organizational structure tree, etc. Every tree involved, there are basically increase, delete, change, or cascade choices. It is good to know first, but I will not repeat them temporarily.
The queue
Queues are arrays with FIFO restrictions, just as we usually queue, only the last in the queue, the first out, can not jump the queue.
Queue applications are also used to deal with ordered tasks that cannot be queued, such as a station system, a ticketing system, etc.
The stack
A stack is similar to a queue, but it is LIFO and can be thought of as a stack of plates, placed from bottom up and taken from top down.
There are function call stacks, parenthesis matching problems, etc.
conclusion
Arrays are a big topic, though it doesn’t sound that fancy, with lots of applications and the cornerstone of some “advanced data structures”.
This article tries to be simple and complicated, but it is inevitable that there will be some things not introduced, there will be some friends feel that the content is much, it is normal, we have different degrees of mastery, what questions need in-depth communication, welcome to leave a message.
After this article, the series of nine, first introduced simple types, then objects, then arrays, I wonder if readers have seen this logic, can guess what the next article about? ~
Arrays are the cornerstone of advanced data structures
Series of articles:
【 Talk about the front end 】 good basic skills, easy to learn with me
Small role, big use — variable
Why is everything an object?
[Talking about the front end] Those “unreasonable value” operations
Digital games in JavaScript
【 Talk about front-end 】 “string” jianghu
【 Talk about the front end 】 Before there is “object”
【 Talk about the front end 】 After “object”