This article was originally published on the CSDN website. The following version has been further revised.

about

  • My blog: Louis Blog
  • SF column: Louis Front end In-depth class
  • Full array decryption in JavaScript

Full text of 13K + words, the system explains the various features of JavaScript array and API.

Array is a very important data type, it is simple, flexible, efficient syntax. Arrays play such a crucial role in most programming languages that it’s hard to imagine a programming language without them. In particular, JavaScript, with its inherent flexibility, further plays the array’s specialty and enriches the array’s use scenarios. It’s no exaggeration to say that without a deep understanding of arrays, you can’t write JavaScript.

By the end of the ES7 specification, the array contains 33 standard API methods and one non-standard API method, with a variety of scenarios and usage scenarios, including many shallow pits, deep pits, and even god pits. We’ll start with the Array constructor and the new ES6 features to help you get to grips with arrays.

Disclaimer: None of the methods specified below are implemented for ES5.

An Array constructor

The Array constructor is used to create a new Array. In general, we recommend using object literals to create arrays, which is a good habit, but there are always times when object literals are weak. For example, I want to create an empty array of length 8. Please compare the following two methods:

// Use the Array constructor
var a = Array(8); / / [undefined x 8]
// Use object literals
var b = [];
b.length = 8; / / [undefined x 8]Copy the code

The Array constructor is obviously a little bit cleaner, and of course you might say, well, object literals are good too, so I’m going to keep quiet.

Above, I used Array(8) instead of new Array(8). Does this matter? In fact, it doesn’t, thanks to the Array constructor’s internal determination of the this pointer, which the ELS5_HTML specification says:

When Array is called as a function rather than as a constructor, It creates and initialises a new Array object. Thus the function call Array(…) Is Equivalent to the object Creation expression new Array(…) with the same arguments.

From the spec, the browser does something similar:

function Array(){
  // If this is not an instance of an Array, create a new instance
  if(! (this instanceof arguments.callee)){
    return new arguments.callee(); }}Copy the code

Above, I seem to have skipped the introduction to the Array constructor syntax, but that’s ok, I’ll fill it in.

The Array constructor has two different treatments, depending on the length of the parameters:

  • New Array (arg1, arg2,…). If the length of an argument is 0 or greater than or equal to 2, the arguments passed in are the 0th through the NTH items of the new array in sequence. (If the length of an argument is 0, an empty array is returned.)
  • New Array(len), if len is not a number, as above, returns an Array containing only len; When len is a value, use the followingspecification, len cannot exceed a maximum of 32 unsigned integers, that is, it must be less than 2 ^ 32Aiaa math.h pow (2) - 1or1 > > > 0), otherwise a RangeError is thrown.

If the argument len is a Number and ToUint32(len) is equal to len, then the length property of the newly constructed object is set to ToUint32(len). If the argument len is a Number and ToUint32(len) is not equal to len, a RangeError exception is thrown.

Above, note the special treatment of the Array constructor for a single numeric parameter. If you only need to use an Array to wrap several parameters of 📦, use array. of. See the next section for details.

New constructor methods in ES6

Due to the common use of arrays, ES6 specifically extends the Array constructor by adding two new methods: array. of and array. from. Let’s talk about it.

Array.of

Array.of is used to convert an argument, in turn, to an item in an Array, and then return the new Array, regardless of whether the argument is a number or otherwise. It is basically the same as the Array constructor, with the only difference being the handling of a single numeric parameter. As follows:

Array.of(8.0); / / [8]
Array(8.0); / / [undefined x 8]Copy the code

Array.of is equivalent to the Array constructor when the arguments are multiple or when a single argument is not a number.

Array.of(8.0.5); / / [8, 5]
Array(8.0.5); / / [8, 5]

Array.of('8'); / / [8]
Array('8'); / / [8]Copy the code

Therefore, if you need to wrap elements in an Array, it is recommended to use the array. of method first.

Currently, the following browsers provide support for Array.of.

Chrome Firefox Edge Safari
45 + 25 + ✔ ️ 9.0 +

Don’t worry if other browsers don’t support it; implementing a polyfill is simple because of the high similarity between Array.of and the Array constructor. As follows:

if (!Array.of){
  Array.of = function(){
    return Array.prototype.slice.call(arguments);
  };
}Copy the code

Array.from

Array.from(arrayLike[, processingFn[, thisArg]])

Array. The from is designed based on other objects to create a new Array of quick and easy, accurate, is from a similar object iteration to create a new Array of an Array of instance, people speaking is, as long as there is an iterator, an object Array. The from can turn it into an Array (of course, is to return the new Array, without changing the original object).

Syntactically, array. from takes three parameters. The first, an array-like object, is mandatory. The second is a processing function that processes the newly generated array before returning it. The third is the this scope, which represents the value of this when the processing function is executed. The last two parameters are optional. Let’s look at the usage.

var obj = {0: 'a'.1: 'b'.2:'c'.length: 3};
Array.from(obj, function(value, index){
  console.log(value, index, this.arguments.length);
  return value.repeat(3); // The return value must be specified, otherwise undefined is returned
}, obj);Copy the code

The execution result is as follows:

Array. From Result

You can see that the this scope of the function is replaced by an obj object. You can also see that by default the function takes two parameters, the value of the current element of the iterator and its index.

Note that once you use the processing function, you must explicitly specify the return value, otherwise undefined is implicitly returned and the resulting array is an empty array containing only a few undefined elements.

In fact, if you don’t need to specify this, the processing function could be an arrow function. The above code can be simplified as follows:

Array.from(obj, (value) => value.repeat(3));Copy the code

Other objects that have iterators include String, Set, Map, arguments, and array. from. As follows:

// String
Array.from('abc'); // ["a", "b", "c"]
// Set
Array.from(new Set(['abc'.'def'])); // ["abc", "def"]
// Map
Array.from(new Map([[1.'abc'], [2.'def']])); / / [[1
, 'abc'], [2.'def']]
// Arguments is a natural array-like object
function fn(){
  return Array.from(arguments);
}
fn(1.2.3); / / [1, 2, 3]Copy the code

At this point you might think that array. from is done, but there is one important extension scenario that must be covered. For example, generating a new Array from 0 to a specified number is easy to do with array. from.

Array.from({length: 10}, (v, i) => i); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]Copy the code

As we’ll see later, it’s probably a little easier to do this with the array keys method.

Currently, the following browsers provide support for array. from.

Chrome Firefox Edge Opera Safari
45 + 32 + ✔ ️ ✔ ️ 9.0 +

Array.isArray

As the name implies, array. isArray is used to determine whether a variable is of an Array type. The weak typing mechanism of JS leads to the fact that judging variable types is a required interview question for a junior front-end developer. I usually use it as the first question to examine a candidate, and then build on that. Before ES5 provided this method, we had at least five ways to determine whether a value was an array:

var a = [];
// 1
a instanceof Array;
// 2. Constructor
a.constructor === Array;
/ / 3. Based on the Object. The prototype. IsPrototypeOf
Array.prototype.isPrototypeOf(a);
// 4. Based on getPrototypeOf
Object.getPrototypeOf(a) === Array.prototype;
/ / 5. Based on the Object. The prototype. ToString
Object.prototype.toString.apply(a) === '[object Array]';Copy the code

Above, in addition to the Object. The prototype. ToString, other method can correctly judge the type of the variable.

Remember that the environment in which code runs is so complex that a variable can use all kinds of tricks to confuse its creator. And look:

var a = {
  __proto__: Array.prototype
};
// Run the following code separately on the console
// 1
a instanceof Array; // true
// 2. Constructor
a.constructor === Array; // true
/ / 3. Based on the Object. The prototype. IsPrototypeOf
Array.prototype.isPrototypeOf(a); // true
// 4. Based on getPrototypeOf
Object.getPrototypeOf(a) === Array.prototype; // trueCopy the code

Above, all four methods return true. Why? Simply manually specifying an object’s __proto__ attribute to array. prototype causes it to inherit from Array. This unaccountable inheritance approach makes the inheritance-based scheme crumble.

Not only that, but we also know that Array is heap data, and variables refer only to the address of its reference, so the address of the Array object reference is different from page to page. An Array declared in an iframe whose constructor is the Array object in the iframe. If an Array x is declared in the iframe and assigned to the variable y on the parent page, then y instanceof Array on the parent page must be false. The last returns a string, so there’s no reference problem. In practice, interactions between multiple pages or systems can only be done with strings.

For those two reasons, I recommend using the last method (don’t mention me), and if you still don’t believe me, here’s an article with exactly the same idea: It is determined with absolute accuracy whether or not a JavaScript object is an array.

In contrast, using array. isArray is very simple, as follows:

Array.isArray([]); // true
Array.isArray({0: 'a'.length: 1}); // falseCopy the code

Currently, the following browsers provide support for array. isArray.

Chrome Firefox IE Opera Safari
5 + 4 + 9 + 10.5 + 5 +

In fact, by the Object. The prototype. ToString to judge the type of a value, is also a leading library standards. So the polyfill for array. isArray usually looks like this:

if (!Array.isArray){
  Array.isArray = function(arg){
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}Copy the code

An array is derived

ES6’s array enhancements go beyond the API and include syntactic sugar. For example, for of, which is a syntactic sugar borrowed from other languages, the syntactic sugar of using for of to generate a new array from the original array, is called array derivation. Array derivation was originally in the draft of ES6, but was removed in version 27 (August 2014) and is currently only supported by Firefox V30 +. Derivation is risky and should be used with caution. Fortunately, all of these languages support derivation today: CoffeeScript, Python, Haskell, Clojure, just to give you an idea. Here we use python’s for in derivation as an example:

# Python for in derivation
a = [1.2.3.4]
print [i * i for i in a if i == 3] # [9]Copy the code

Here is the SpiderMonkey engine (Firefox) previously implemented an array derivation based on the ES4 specification (very similar to the Python derivation) :

[i * i for (i of a)] // [1, 4, 9, 16]Copy the code

The array for of in ES6 is an evolution of ES4, with the for keyword first, in in in the middle, and the operation expression last. As follows:

[for (i of [1.2.3.4]) i * i] // [1, 4, 9, 16]Copy the code

As in the Python example, for of in ES6 can also be used with an if statement related to arrays:

/ / a single the if
[for (i of [1.2.3.4]) if (i == 3) i * i] / / [9]
// Even multiple ifs
[for (i of [1.2.3.4]) if (i > 2) if (i < 4) i * i] / / [9]Copy the code

Even more powerful, ES6 array derivation also allows multiple for of.

[for (i of [1.2.3]) for (j of [10.100]) i * j] // [10, 100, 20, 200, 30, 300]Copy the code

Even an array derivation can be embedded in another array derivation.

[for (i of [1.2.3[])for (j of [10.100]) i * j] ] // [[10, 100], [20, 200], [30, 300]]Copy the code

The only difference between the former and the latter is that the second derivation of the latter is to return the array and then perform an operation with the external derivation.

In addition to nesting multiple array derivations, ES6’s array derivations also assign a new scope for each iteration (currently Firefox also does not create a new scope for each iteration) :

/ / ES6 specification
[for (x of [0.1.2]) () => x][0] ()/ / 0
/ / run Firefox
[for (x of [0.1.2]) () => x][0] ()/ / 2Copy the code

From the above example, we can see that using array derivation to create new arrays is much simpler than using forEach, map, filter, and other traversal methods, but unfortunately, it is not the standard specification.

Not only does ES6 add an API for the Array constructor, it also adds methods for eight prototypes. I will intersperse the introduction of the prototype method with the ES6 related method, so please read on.

The prototype

The common sense of inheritance tells us that all Array methods in js are derived from array. prototype. As with other constructors, you can add methods to all Array instances by extending the method on Array’s prototype property.

It’s worth noting that Array.prototype is itself an Array.

Array.isArray(Array.prototype); // true
console.log(Array.prototype.length);/ / 0Copy the code

The following methods can be further verified:

console.log([].__proto__.length);/ / 0
console.log([].__proto__);// [Symbol(Symbol.unscopables): Object]Copy the code

For more information on symbols (symbol.unscopables), please refer to the following section.

methods

Array prototype provides a large number of methods, mainly divided into three types, one will change its value, one does not change its value, and the other is the traversal method.

Array.prototype has some properties set to [[DontEnum]], so it is not possible to iterate in the usual way. We can obtain all methods of Array.prototype as follows:

Object.getOwnPropertyNames(Array.prototype); // ["length", "constructor", "toString", "toLocaleString", "join", "pop", "push", "reverse", "shift", "unshift", "slice", "splice", "sort", "filter", "forEach", "some", "every", "map", "indexOf", "lastIndexOf", "reduce", "reduceRight", "copyWithin", "find", "findIndex", "fill", "includes", "entries", "keys", "concat"]Copy the code

Ways to Change Your Value (9)

Based on ES6, there are altogether 9 methods to change its own value, namely pop, push, reverse, shift, sort, splice, unshift, and the two newly added methods copyWithin and fill in ES6.

For the array method that can change its own value, special attention should be paid in daily development, and try to avoid changing the items of the original array in the loop. Next, let’s take a closer look at these methods.

pop

The pop() method removes the last element from an array and returns that element. In the case of a stack, this process is called a top stack pop.

var array = ["cat"."dog"."cow"."chicken"."mouse"];
var item = array.pop();
console.log(array); // ["cat", "dog", "cow", "chicken"]
console.log(item); // mouseCopy the code

Because of its clever design, the POP method can be applied to array-like objects, known as duck typing. As follows:

var o = {0:"cat".1:"dog".2:"cow".3:"chicken".4:"mouse".length:5}
var item = Array.prototype.pop.call(o);
console.log(o); // Object {0: "cat", 1: "dog", 2: "cow", 3: "chicken", length: 4}
console.log(item); // mouseCopy the code

But if an array-like object does not have a length property, then the object will be created with a length property with a value of 0. As follows:

var o = {0:"cat".1:"dog".2:"cow".3:"chicken".4:"mouse"}
var item = Array.prototype.pop.call(o);
console.log(array); // Object {0: "cat", 1: "dog", 2: "cow", 3: "chicken", 4: "mouse", length: 0}
console.log(item); // undefinedCopy the code
push

The push() method adds one or more elements to the end of the array and returns the new length of the array. In the case of a stack, this process is called top stack pushing.

Arr. Push (element1,… , elementN)

var array = ["football"."basketball"."volleyball"."Table tennis"."badminton"];
var i = array.push("golfball");
console.log(array); // ["football", "basketball", "volleyball", "Table tennis", "badminton", "golfball"]
console.log(i); / / 6Copy the code

Like pop, push can be applied to array-like objects. If length cannot be converted to a number or if the length attribute does not exist, then the inserted element has an index of 0 and is created if the length attribute does not exist.

var o = {0:"football".1:"basketball"};
var i = Array.prototype.push.call(o, "golfball");
console.log(o); // Object {0: "golfball", 1: "basketball", length: 1}
console.log(i); / / 1Copy the code

In fact, the push method uses the length attribute to determine where to start inserting a given value.

var o = {0:"football".1:"basketball".length:1};
var i = Array.prototype.push.call(o,"golfball");
console.log(o); // Object {0: "football", 1: "golfball", length: 2}
console.log(i); / / 2Copy the code

By using the feature of push to insert elements according to the length attribute, the array can be merged as follows:

var array = ["football"."basketball"];
var array2 = ["volleyball"."golfball"];
var i = Array.prototype.push.apply(array,array2);
console.log(array); // ["football", "basketball", "volleyball", "golfball"]
console.log(i); / / 4Copy the code
reverse

The reverse() method reverses the positions of the elements in the array, so that the first becomes the last, and the last becomes the first, and returns a reference to the array.

Grammar: arr. Reverse ()

var array = [1.2.3.4.5];
var array2 = array.reverse();
console.log(array); / /,4,3,2,1 [5]
console.log(array2===array); // trueCopy the code

Similarly, reverse is also a beneficiary of duck discrimination, since the range of inverted elements is restricted by the length attribute. As follows:

var o = {0:"a".1:"b".2:"c".length:2};
var o2 = Array.prototype.reverse.call(o);
console.log(o); // Object {0: "b", 1: "a", 2: "c", length: 2}
console.log(o === o2); // trueCopy the code

If the length property is less than 2 or if the length property is not numeric, then the original array-like object will remain unchanged. This object does not create the length property even if it does not exist. In particular, when the length attribute is large, the “index” of the array-like object will be as close to length as possible. As follows:

var o = {0:"a".1:"b".2:"c".length:100};
var o2 = Array.prototype.reverse.call(o);
console.log(o); // Object {97: "c", 98: "b", 99: "a", length: 100}
console.log(o === o2); // trueCopy the code
shift

The shift() method removes the first element of the array and returns that element.

Grammar: arr. The shift ()

var array = [1.2.3.4.5];
var item = array.shift();
console.log(array); / / 5-tetrafluorobenzoic [2]
console.log(item); / / 1Copy the code

Also benefiting from duck typing, Shift can still handle array-like objects. As follows:

var o = {0:"a".1:"b".2:"c".length:3};
var item = Array.prototype.shift.call(o);
console.log(o); // Object {0: "b", 1: "c", length: 2}
console.log(item); // aCopy the code

If the length property of an array-like object does not exist, the length property is added and initialized to 0. As follows:

var o = {0:"a".1:"b".2:"c"};
var item = Array.prototype.shift.call(o);
console.log(o); // Object {0: "a", 1: "b", 2:"c" length: 0}
console.log(item); // undefinedCopy the code
sort

The sort() method sorts the elements of the array and returns the array. The sort method is a little more complicated, and I’ll spend a little more time on it here.

Grammar: arr. Sort ([comparefn])

Comparefn is optional; if omitted, the array elements will be sorted by their Respective Unicode point of convert to string. For example, “Boy” will come before “apple”. When sorting numbers, 25 will come before 8, because as a string, “25” will come before “8”. Such as:

var array = ["apple"."Boy"."Cat"."dog"];
var array2 = array.sort();
console.log(array); // ["Boy", "Cat", "apple", "dog"]
console.log(array2 == array); // true

array = [10.1.3.20];
var array3 = array.sort();
console.log(array3); // [1, 10, 20, 3]Copy the code

If comparefn is specified, the array is sorted by the return value of the call to that function. If a and B are two elements to be compared:

  • If comparefn(a, b) < 0, then a will rank before B;
  • If comparefn(a, b) = 0, then the relative positions of a and b are unchanged;
  • If comparefn(a, b) > 0, then a, b will switch positions;

If the array elements are numbers, the sort function comparefn has the following format:

function compare(a, b){
  return a-b;
}Copy the code

If the array elements are strings of non-ASCII characters (such as strings containing non-English characters such as E, e, e, a, a, or Chinese characters), you need to use string.localecompare. The following function will be in the correct order.

var array = ['each other'.'united'.'net'.'instead of'.'change'.'the'.'world'];
var array2 = array.sort();

var array = ['each other'.'united'.'net'.'instead of'.'change'.'the'.'world']; Array2 = array2; array2 = array2
var array3 = array.sort(function (a, b) {
  return a.localeCompare(b);
});

console.log(array2); // [" world ", "mutual "," change ", "change "," boundary ", "net "," union "]
console.log(array3); // [" change ", "change "," mutual ", "boundary "," union ", "world "," net "]Copy the code

As mentioned above, for the “Internet Changed the world” array, sort defaults to sorting the array elements as Unicode strings. In reality, however, we expect the array elements to be sorted in pinyin order, and obviously string.localecompare helps us achieve this.

The reason we need to reassign the array in the above test is because sort changes the array itself each time it sorts and returns a reference to the array. If you don’t do this, array2 and Array3 will point to the same array after two consecutive sorts, ultimately affecting our test. The reassignment of the array disconnects the reference to the original array.

As above, sort also benefits from duck styles, such as:

var o = {0:'each other'.1:'united'.2:'net'.3:'instead of'.4:'change'.5:'the'.6:'world'.length:7};
Array.prototype.sort.call(o,function(a, b){
  return a.localeCompare(b);
});
console.log(o); / / Object {0: "change", 1: "change", 2: "each other", 3: "world", 4: "coupon", 5: "the world", 6: "net", length: 7}, visible with the sorting resultCopy the code

Note: When using sort’s duck sorting feature, array-like objects that do not have a length property will not be sorted, nor will the length property be added to them.

var o = {0:'each other'.1:'united'.2:'net'.3:'instead of'.4:'change'.5:'the'.6:'world'};
Array.prototype.sort.call(o,function(a, b){
  return a.localeCompare(b);
});
console.log(o); / / Object {0: "each other", 1: "coupon", 2: "net", 3: "change", 4: "change", 5: "the world", 6: "community"}, did not add the length attributeCopy the code
Use mapping to improve sorting

If you need to convert the elements of an array multiple times to achieve sorting, then using map to assist sorting is a good choice. The basic idea is to take the actual value of each element in the array, sort it and then restore the array.

// The array to be sorted
var array = ['dog'.'Cat'.'Boy'.'apple'];
// Temporary storage of numbers and positions to be sorted
var mapped = array.map(function(el, i) {
  return { index: i, value: el.toLowerCase() };
})
// Sort the array by multiple values
mapped.sort(function(a, b) {
  return +(a.value > b.value) || +(a.value === b.value) - 1;
});
// Get sorted by index
var result = mapped.map(function(el){
  return array[el.index];
});
console.log(result); // ["apple", "Boy", "Cat", "dog"]Copy the code
Strange chrome

In fact, the ECMAscript specification does not specify a specific sort algorithm, which results in different sort algorithms for different browsers.

var array = [{ n: "a".v: 1 }, { n: "b".v: 1 }, { n: "c".v: 1 }, { n: "d".v: 1 }, { n: "e".v: 1 }, { n: "f".v: 1 }, { n: "g".v: 1 }, { n: "h".v: 1 }, { n: "i".v: 1 }, { n: "j".v: 1 }, { n: "k".v: 1},]; array.sort(function (a, b) {
    return a.v - b.v;
});
for (var i = 0,len = array.length; i < len; i++) {
    console.log(array[i].n);
}
// f a c d e b g h i j kCopy the code

Because the v values are equal, the array sort should be the same before and after the array sort. However, Chrome behaves abnormally while other browsers (such as IE or Firefox) behave normally.

This is because v8 engines use unstable sorting for efficient sorting. That is, when the array length exceeds 10, another sort method (quicksort) is called. For 10 or less, insert sort is used, and the result will be stable as follows:

var array = [{ n: "a".v: 1 }, { n: "b".v: 1 }, { n: "c".v: 1 }, { n: "d".v: 1 }, { n: "e".v: 1 }, { n: "f".v: 1 }, { n: "g".v: 1 }, { n: "h".v: 1 }, { n: "i".v: 1 }, { n: "j".v: 1 },];
array.sort(function (a, b) {
  return a.v - b.v;
});
for (var i = 0,len = array.length; i < len; i++) {
  console.log(array[i].n);
}
// a b c d e f g h i jCopy the code

There are exactly 10 pieces of data from A to J.

So how can you avoid this “bug” in Chrome? It’s as simple as changing the return value of the sorting method, as follows:

array.sort(function (a, b) {
  return a.v - b.v || array.indexOf(a)-array.indexOf(b);
});Copy the code

One thing to note when using array sort is that the internal algorithm for sort varies from browser to browser. Try to only return -1, 0, and 1. Do not attempt to return other values such as true or false, as this may lead to unreliable sorting results.

Problem analysis

What happens if the sort function passed into the sort method returns a Boolean value?

Here are some common browsers and script engines:

Browser Name ECMAScript Engine
Internet Explorer 6 – 8 JScript
Internet Explorer 9 – 10 Chakra
Firefox SpiderMonkey, IonMonkey, TraceMonkey
Chrome V8
Safair JavaScriptCore(SquirrelFish Extreme)
Opera Carakan

Analyze the following code, which expects to sort the array elements in ascending order:

var array = [7.6.5.4.3.2.1.0.8.9];
var comparefn = function (x, y) {
  return x > y;
};
array.sort(comparefn);Copy the code

In code, comparefn returns a bool, not -1, 0, or 1 as specified by the specification. Then execute this code, how is the JS script engine implementation?

The output Whether it meets expectations
JScript [2, 3, 5, 1, 4, 6, 7, 0, 8, 9] no
Carakan [0, 1, 3, 8, 2, 4, 9, 5, 6, 7] no
Chakra & JavaScriptCore [7, 6, 5, 4, 3, 2, 1, 0, 8, 9] no
SpiderMonkey [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] is
V8 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] is

According to the data in the table, when the number of elements in the array is less than or equal to 10, the phenomenon is as follows:

  • Error in JScript & Carakan sorting result
  • Chakra & JavaScriptCore does not appear to be sorted
  • SpiderMonkey returned the expected correct result
  • V8 seems to be sorted correctly for now

Expand the array element to 11 bits, as follows:

var array = [7.6.5.4.3.2.1.0.10.9.8];
var comparefn = function (x, y) {
  return x > y;
};
array.sort(comparefn);Copy the code
JavaScript engine The output Whether it meets expectations
JScript [2, 3, 5, 1, 4, 6, 7, 0, 8, 9, 10] no
Carakan [0, 1, 3, 8, 2, 4, 9, 5, 10, 6, 7] no
Chakra & JavaScriptCore [7, 6, 5, 4, 3, 2, 1, 0, 10, 8, 9] no
IonMonkey [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] is
V8 [5, 0, 1, 2, 3, 4, 6, 7, 8, 9, 10] no

According to the data in the table, when the number of elements in the array is greater than 10:

  • Error in JScript & Carakan sorting result
  • Chakra & JavaScriptCore does not appear to be sorted
  • SpiderMonkey returned the expected correct result
  • V8 sort result changed from correct to incorrect
splice

The splice() method modifies the array by replacing old elements with new ones. Splice is a common method, and it can be used in complex array manipulation scenarios, especially when you need to maintain the original array reference, delete in place or add elements, splice is the most suitable.

Splice (start,deleteCount[, item1[, item2[,…]])

Start Specifies where to start modifying content. If the length of the array is exceeded, the contents are added from the end of the array. If it is a negative value, it specifies an index position equal to Length +start (length is the length of the array), indicating the start bit starting from the end of the array.

DeleteCount Specifies the number of elements to be deleted. If it is equal to 0, it is not deleted. In this case, at least one new element should be added, and if it is greater than the sum of the elements after start, start and all the elements after start will be removed.

ItemN specifies the element to be added. By default, this method removes only array elements.

The return value is an array of deleted elements from the original array, or an empty array if not deleted.

Here are some examples:

var array = ["apple"."boy"];
var splices = array.splice(1.1);
console.log(array); // ["apple"]
console.log(splices); // ["boy"]; // ["boy"]; // ["boy"]

array = ["apple"."boy"];
splices = array.splice(2.1."cat");
console.log(array); // ["apple", "boy", "cat"]
console.log(splices); // [], we can see that since start exceeds the length of the array, we will start to add elements from the end of the array, and the original array will not be deleted

array = ["apple"."boy"];
splices = array.splice(2 -.1."cat");
console.log(array); // ["cat", "boy"]
console.log(splices); // ["apple"], we can see that when start is negative, we delete an element from the end of the array starting at the -start bit, and insert an element from there

array = ["apple"."boy"];
splices = array.splice(- 3.1."cat");
console.log(array); // ["cat", "boy"]
console.log(splices); // ["apple"]; if -start exceeds the length of the array, the array is deleted from the first place by default

array = ["apple"."boy"];
splices = array.splice(0.3."cat");
console.log(array); // ["cat"]
console.log(splices); // ["apple", "boy"]; if deleteCount is greater than the sum of the elements after start, all the elements after start will be deletedCopy the code

As above, Splice also benefits from duck styles, such as:

var o = {0:"apple".1:"boy".length:2};
var splices = Array.prototype.splice.call(o,1.1);
console.log(o); // Object {0: "apple", length: 1}
console.log(splices); // ["boy"]Copy the code

Note: If an array-like object does not have a length property, splice will add a length property to the array-like object and initialize it to 0. (Examples omitted here, please comment in the comments if necessary)

If you need to delete an existing element from an array, see the following:

var array = ['a'.'b'.'c'];
array.splice(array.indexOf('b'),1);Copy the code
unshift

The unshift() method inserts elements at the beginning of the array (just like at the bottom of the stack) and returns the new length of the array.

Syntax: arr. Unshift (element1,… , elementN)

var array = ["red"."green"."blue"];
var length = array.unshift("yellow");
console.log(array); // ["yellow", "red", "green", "blue"]
console.log(length); / / 4Copy the code

What if we pass an array to the unshift method?

var array = ["red"."green"."blue"];
var length = array.unshift(["yellow"]);
console.log(array); // [["yellow"], "red", "green", "blue"]
console.log(length); // 4, the visible array can also be inserted successfullyCopy the code

As above, unshift also benefits from the duck shape, presenting chestnuts:

var o = {0:"red".1:"green".2:"blue".length:3};
var length = Array.prototype.unshift.call(o,"gray");
console.log(o); // Object {0: "gray", 1: "red", 2: "green", 3: "blue", length: 4}
console.log(length); / / 4Copy the code

Object {0: “gray”, 1: “green”, 2: “blue”, length: 0: “gray”, 1: “green”, 2: “blue”, length: 1}, shift will assume that the length of the array is 0, and will start the insertion at the object’s subscript of 0. The position property will be replaced, and the length property of the array-like object will be initialized to the number of elements to be inserted.

copyWithin(ES6)

The copyWithin() method, based on the ECMAScript 2015 (ES6) specification, is used for the replacement of elements within an array, i.e. both the replacing element and the replaced element are elements within the array.

Syntax: arr.copyWithin(target, start[, end = this.length])

Taget specifies the index of the element to be replaced, start specifies the index of the beginning of the element to be replaced, and end, optional, refers to the index at the end of the element to be replaced.

If start is negative, the specified index position is equal to Length +start, where length is the length of the array. The same goes for end.

Note: Only Firefox (version 32 and above) currently implements this method.

var array = [1.2.3.4.5]; 
var array2 = array.copyWithin(0.3);
console.log(array===array2,array2); // true [4, 5, 3, 4, 5]

var array = [1.2.3.4.5]; 
console.log(array.copyWithin(0.3.4)); // [4, 2, 3, 4, 5]

var array = [1.2.3.4.5]; 
console.log(array.copyWithin(0.2 -.- 1)); // [4, 2, 3, 4, 5]Copy the code

Similarly, copyWithin also benefits from duck differentiation, such as:

var o = {0:1.1:2.2:3.3:4.4:5.length:5}
var o2 = Array.prototype.copyWithin.call(o,0.3);
console.log(o===o2,o2); // True Object {0=4, 1=5, 2=3, more... }Copy the code

To use the copyWithin method in a browser other than Firefox, refer to Polyfill.

fill(ES6)

The fill() method, which is based on the ECMAScript 2015 (ES6) specification, is also used for array element replacement, but is slightly different from copyWithin in that it is primarily used to replace elements within a specified range of an array with a value.

Syntax: arr.fill(value, start[, end = this.length])

Value specifies the value to be replaced, start specifies the index at which the element to be replaced begins, and end, optional, refers to the index at which the element to be replaced ends.

If start is negative, the specified index position is equal to Length +start, where length is the length of the array. The same goes for end.

Note: Only Firefox (version 31 and above) currently implements this method.

var array = [1.2.3.4.5];
var array2 = array.fill(10.0.3);
console.log(array===array2,array2); // true [10, 10, 10, 4, 5]
// For other examples, see copyWithinCopy the code

As above, fill also benefits from the duck form, such as:

var o = {0:1.1:2.2:3.3:4.4:5.length:5}
var o2 = Array.prototype.fill.call(o,10.0.2);
console.log(o===o2,o2); true Object { 0=10.1=10.2=3And more... }Copy the code

To use the fill method in a browser other than Firefox, see Polyfill.

Ways to Not Change Yourself (9)

There are nine methods that will not change themselves based on ES7. They are Concat, Join, Slice, toString, toLocateString, indexOf, lastIndexOf, non-standard toSource, and ES7 new includes.

concat

The concat() method merges the passed array or elements into a new array and returns it.

Syntax: arr.concat(value1, value2,… , valueN)

var array = [1.2.3];
var array2 = array.concat(4[5.6], [7.8.9]);
console.log(array2); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(array); // [1, 2, 3]Copy the code

If no arguments are passed in the concat method, a new array (pointing to the new address space) is generated based on a shallow copy of the original array.

var array = [{a: 1}];
var array3 = array.concat();
console.log(array3); // [{a: 1}]
console.log(array3 === array); // false
console.log(array[0] === array3[0]); // true, the first element of the new array still shares a reference to the same objectCopy the code

As above, Concat also benefits from duck differentiation, but its effect may not be as good as we would like, as follows:

var o = {0:"a".1:"b".2:"c".length:3};
var o2 = Array.prototype.concat.call(o,'d', {3:'e'.4:'f'.length:2},'g'.'h'.'i']);
console.log(o2); // [{0:"a", 1:"b", 2:"c", length:3}, 'd', {3:'e', 4:'f', length:2}, 'g', 'h', 'i']Copy the code

As you can see, an array-like object is still returned as an array, not what we expect.

join

The join() method concatenates all elements of an array into a single string.

Syntax: arr.join([separator = ‘,’]) Separator optional; by default, it is a comma.

var array = ['We'.'are'.'Chinese'];
console.log(array.join()); // "We,are,Chinese"
console.log(array.join('+')); // "We+are+Chinese"
console.log(array.join(' ')); // "WeareChinese"Copy the code

As above, join also benefits from duck differentiation, as follows:

var o = {0:"We".1:"are".2:"Chinese".length:3};
console.log(Array.prototype.join.call(o,'+')); // "We+are+Chinese"
console.log(Array.prototype.join.call('abc')); // "a,b,c"Copy the code
slice

The slice() method shallowly copies a portion of the array into a new array object and returns the array object.

Syntax: arr.slice([start[, end]])

The start parameter specifies the index of the start position of the replication, and the end, if there is a value, indicates the index of the end position (excluding this position).

If the value of start is negative, if the array length is length, then the copy starts at the position of length+start. If end has a value, it must be a negative value greater than start. Otherwise, an empty array is returned.

When the slice parameter is null, a shallow copy generates a new array, just like the concat method.

var array = ["one"."two"."three"."four"."five"];
console.log(array.slice()); // ["one", "two", "three","four", "five"]
console.log(array.slice(2.3)); // ["three"]Copy the code

Shallow replication is when an object is copied, only a reference to the object is copied, and the reference is still to the same object. Here’s why Slice is a shallow copy.

var array = [{color:"yellow"}, 2.3];
var array2 = array.slice(0.1);
console.log(array2); // [{color:"yellow"}]
array[0] ["color"] = "blue";
console.log(array2); // [{color:"bule"}]Copy the code

Since slice is a shallow copy, the object copied to is only a reference. Change the value of array, and array2 changes accordingly.

Also, we can easily retrieve the last element of the array by taking advantage of the fact that the first parameter of the slice method is negative, as follows:

console.log([1.2.3].slice(- 1));/ / [3]Copy the code

Slice also benefits from the duck style. As follows:

var o = {0: {"color":"yellow"}, 1:2.2:3.length:3};
var o2 = Array.prototype.slice.call(o,0.1);
console.log(o2); // [{color: yellow}]Copy the code

Since the following versions of Internet Explorer 9 do not support this method well, please refer to Polyfill for better support of earlier versions of Internet Explorer.

toString

The toString() method returns a string form of an array consisting of the return value of toString() for each element in the array joined (separated by commas) by calling the join() method.

Grammar: arr. ToString ()

var array = ['Jan'.'Feb'.'Mar'.'Apr'];
var str = array.toString();
console.log(str); // Jan,Feb,Mar,AprCopy the code

When an array is concatenated directly with a string, its toString() method is automatically called.

var str = ['Jan'.'Feb'.'Mar'.'Apr'] + ',May';
console.log(str); // "Jan,Feb,Mar,Apr,May"
// Now let's try duck style
var o = {0:'Jan'.1:'Feb'.2:'Mar'.length:3};
var o2 = Array.prototype.toString.call(o);
console.log(o2); // [object Object]
console.log(o.toString()==o2); // trueCopy the code

Visible, Array. The prototype. The toString () method when handling class Array Object, call directly to class Array Object Object. The prototype. The toString () method is completely consistent, say good duck type distinguishes the type?

According to ES5 semantics, the toString() method is generic and can be used on any object. If the Object has a join () method, which will be called, the return value is returned, not the call Object. The prototype. The toString (), to that end, we add a join to o Object method. As follows:

var o = {
  0:'Jan'.1:'Feb'.2:'Mar'.length:3.join:function(){
    return Array.prototype.join.call(this); }};console.log(Array.prototype.toString.call(o)); // "Jan,Feb,Mar"Copy the code
toLocaleString

ToLocaleString () is a variant of toString(), which consists of the return value of toLocaleString() for each element in the array joined (separated by commas) by calling the join() method.

Grammar: arr. ToLocaleString ()

The elements in the array call their respective toLocaleString methods:

  • Object:Object.prototype.toLocaleString()
  • Number:Number.prototype.toLocaleString()
  • Date:Date.prototype.toLocaleString()
var array= [{name:'zz'}, 123."abc".new Date()];
var str = array.toLocaleString();
console.log(str); // [Object Object],123, ABC,2016/1/5 PM 1:06:23Copy the code

The duck form is also written in the same way as toString, as follows:

var o = {
  0:123.1:'abc'.2:new Date(), 
  length:3.join:function(){
    return Array.prototype.join.call(this); }};console.log(Array.prototype.toLocaleString.call(o)); // 123, ABC,2016/1/5 PM 1:16:50Copy the code
indexOf

The indexOf() method is used to find the indexOf an element at its first occurrence in the array, and returns -1 if none is present.

Syntax: arr. IndexOf (element, fromIndex=0)

Element is the element to find.

FromIndex indicates the start search location. The default value is 0. If the length of the array is exceeded, -1 is returned. If the value is negative, then the array will be searched from the end of the array, assuming the length of the array is length. If length + fromIndex<0, the entire array will be searched.

IndexOf uses strict equality (that is, using === to match the elements in the array).

var array = ['abc'.'def'.'ghi'.'123'];
console.log(array.indexOf('def')); / / 1
console.log(array.indexOf('def'.- 1)); // If the search fails, return -1
console.log(array.indexOf('def'.4 -)); // 1 Since 4 is larger than the array, the entire array will be looked up, so return 1
console.log(array.indexOf(123)); // -1 does not match the string '123' because it is a strict matchCopy the code

Thanks to duck typing, indexOf can handle array-like objects. As follows:

var o = {0:'abc'.1:'def'.2:'ghi'.length:3};
console.log(Array.prototype.indexOf.call(o,'ghi'.4 -));/ / 2Copy the code

However, this method does not support versions below IE9. To better support earlier versions of IE (IE6 to 8), see Polyfill.

lastIndexOf

The lastIndexOf() method is used to find the index of the last occurrence of an element in the array, and returns -1 if none was found. And it’s a reverse lookup of indexOf, looking forward from the last in the array.

Syntax: arr.lastIndexOf(element, fromIndex=length-1)

Element is the element to find.

FromIndex indicates the start search position. The default value is array length-1. If we exceed the length of the array, the entire array is searched because we are looking backwards. If length + fromIndex<0, the array is not searched. If length + fromIndex<0, the array is not searched.

Like indexOf, lastIndexOf strictly matches array elements.

For example, see indexOf, which is compatible with Internet Explorer of earlier versions (IE6 to 8). For example, see Polyfill.

includes(ES7)

The includes() method is based on the ECMAScript 2016 (ES7) specification. It determines whether the current array contains a specified value, returning true if it does, false otherwise.

Syntax: arr.includes(element, fromIndex=0)

Element is the element to find.

FromIndex searches for elements from the index, which defaults to 0. It is a forward lookup, that is, from the index to the end of the array.

var array = [1.2.NaN];
console.log(array.includes(1)); // true
console.log(array.includes(NaN)); // true
console.log(array.includes(2.4 -)); // trueCopy the code

This method also benefits from duck pattern recognition. As follows:

var o = {0:'a'.1:'b'.2:'c'.length:3};
var bool = Array.prototype.includes.call(o, 'a');
console.log(bool); // trueCopy the code

This method is only implemented in Chrome 47, Opera 34, Safari 9 and later. For additional browser support, see Polyfill.

toSource

The toSource() method is nonstandard. It returns the source code for the array and is currently only implemented by Firefox.

Grammar: arr. ToSource ()

var array = ['a'.'b'.'c'];
console.log(array.toSource()); // ["a", "b", "c"]
// Test the duck shape
var o = {0:'a'.1:'b'.2:'c'.length:3};
console.log(Array.prototype.toSource.call(o)); // ["a","b","c"]Copy the code

Traversal methods (12)

Based on ES6, there are altogether 12 methods that will not change themselves, including forEach, every, some, filter, map, Reduce, reduceRight and entries, find, findIndex, keys and values newly added in ES6.

forEach

The forEach() method specifies that each element of the array executes the passed function once, returning undefined.

Syntax: arr.forEach(fn, thisArg)

Fn represents the function to execute on each item of the array, taking three arguments:

  • Value Specifies the value of the element being processed
  • Index Indicates the array index of the current element
  • Array itself

ThisArg is optional and is used as the this object within the fn function.

ForEach performs fn once forEach item in the array. Items that have been deleted, added, or never assigned are skipped (except for items with undefined values).

During the traversal, FN is passed the above three parameters.

var array = [1.3.5];
var obj = {name:'cc'};
var sReturn = array.forEach(function(value, index, array){
  array[index] = value * value;
  console.log(this.name); // cc is printed three times
},obj);
console.log(array); // [1, 9, 25]
console.log(sReturn); // The return value is undefinedCopy the code

Thanks to duck typing, forEach can iterate over array-like objects via call, although it can’t directly iterate over objects. As follows:

var o = {0:1.1:3.2:5.length:3};
Array.prototype.forEach.call(o,function(value, index, obj){
  console.log(value,index,obj);
  obj[index] = value * value;
},o);
// 1 0 Object {0: 1, 1: 3, 2: 5, length: 3}
// 3 1 Object {0: 1, 1: 3, 2: 5, length: 3}
// 5 2 Object {0: 1, 1: 9, 2: 5, length: 3}
console.log(o); // Object {0: 1, 1: 9, 2: 25, length: 3}Copy the code

ForEach does not exit the loop directly. ForEach can only use return to continue in a for loop. ForEach cannot be used in earlier versions of IE (6-8). Please refer to Polyfill for compatibility writing.

every

Every () uses the passed function to test all the elements. As long as one of the functions returns false, the result of the method is false; If all returns true, then the result of this method is true. Therefore, every method has the following rules:

  • If we want to detect an element greater than 100 (one > 100), we need to construct “false” in the passed function (item <= 100), and the result of the whole method is false to indicate that there are elements in the array that satisfy the condition. One false ===> false
  • To check whether all elements in the array are greater than 100, we need to construct the return value “true” in the passed function (that is, return item > 100). If the entire method results in true, it means that all elements of the array satisfy the condition. All true ===> true

The syntax is the same as forEach. For details, see every in detail JS traversal.

Here is how to write duck style:

var o = {0:10.1:8.2:25.length:3};
var bool = Array.prototype.every.call(o,function(value, index, obj){
  return value >= 8;
},o);
console.log(bool); // trueCopy the code

Every cannot be used in earlier versions of IE(6~8). Please refer to Polyfill for the compatible writing method.

some

The some() method is the opposite of every() in that it returns true if one of the functions returns true, and false if all of them return false. Some methods have the following rules:

  • To detect an element greater than 100 in the array, we need to construct “true” in the passed function (i.e., return item > 100). One true ===> true
  • To check whether all elements in the array are greater than 100 (i.e., all > 100), we need to construct “false” in the passed function (i.e., return item <= 100), and the entire method result is false to indicate that all elements in the array satisfy the condition. All false ===> false

If you notice that the some method does the same thing as the includes method, it probes whether the array has an element that meets the criteria and returns true if it does. Observing and summarizing these subtle relationships can help us understand how they work.

Some can be written as every, which is also not available in earlier versions of IE (6~8). For compatibility, please refer to Polyfill.

filter

The filter() method uses the passed function to test all the elements and returns a new array of all the elements that passed the test. It acts as a filter, sifting out elements that don’t fit.

Syntax: arr.filter(fn, thisArg)

var array = [18.9.10.35.80];
var array2 = array.filter(function(value, index, array){
  return value > 20;
});
console.log(array2); / / [35, 80]Copy the code

Filter also supports duck type discrimination. For details, please refer to the writing method of duck type discrimination of every method. Please refer to Polyfill for compatibility in lower IE versions (6~8).

map

The map() method iterates through the array, processing each element with the passed function, and returning a new array of the function’s return values.

Syntax: arr.map(fn, thisArg)

The parameters are the same as those of the forEach method.

Please refer to the detailed JS traversal map explanation.

Map also supports duck type discrimination. For details, please refer to the writing method of every duck type discrimination.

Please refer to Polyfill for compatibility in lower IE versions (6~8).

reduce

The reduce() method receives a method as an accumulator, and each value in the array (from left to right) is merged to end up with a single value.

Syntax: arr.reduce(fn, initialValue)

Fn represents the function that executes on each item of the array, taking four arguments:

  • PreviousValue The value returned by the callback on the last call, or the initial value provided
  • Value Specifies the value of the element currently being processed in the array
  • Index Indicates the index of the current element in the array
  • Array Array itself

InitialValue specifies the first argument to the first call to FN.

When fn is first executed:

  • If initialValue is provided when reduce is called, then the first previousValue will be equal to initialValue, in which case item is equal to the first value in the array;
  • If initialValue is not provided, then previousVaule equals the first value in the array and item equals the second value in the array. If the array is empty at this point, TypeError will be raised.
  • If an array has only one element and an initialValue is not provided, or if an initialValue is provided but the array is empty, then FN is not executed and the unique value of the array is returned.
var array = [1.2.3.4];
var s = array.reduce(function(previousValue, value, index, array){
  return previousValue * value;
},1);
console.log(s); / / 24
// ES6 is more concise
array.reduce((p, v) = > p * v); / / 24Copy the code

The above callback is called four times, each time the parameters and returns are shown in the following table:

callback previousValue currentValue index array return value
The first 1 1 1 [1, 2, 3, 4] 1
The 2nd 1 2 2 [1, 2, 3, 4] 2
The third time 2 3 3 [1, 2, 3, 4] 6
4 times 6 4 4 [1, 2, 3, 4] 24

Reduce also supports duck type discrimination. For details, refer to the duck type discrimination writing of every method.

Please refer to Polyfill for compatibility in lower IE versions (6~8).

reduceRight

The reduceRight() method receives a method as an accumulator, and each value in the array is merged (from right to left) to end up with a single value. The execution direction of reduce is the same as that of Reduce except in the opposite direction. For details, see the description of reduce.

Please refer to Polyfill for compatibility in lower IE versions (6~8).

entries(ES6)

The entries() method, based on the ECMAScript 2015 (ES6) specification, returns an array iterator object containing key-value pairs for each index in the array.

Grammar: arr. Entries ()

var array = ["a"."b"."c"];
var iterator = array.entries();
console.log(iterator.next().value); // [0, "a"]
console.log(iterator.next().value); // [1, "b"]
console.log(iterator.next().value); // [2, "c"]
console.log(iterator.next().value); // if the iterator is at the end of the array, the iterator will return undefinedCopy the code

Clearly, Entries also benefited from duck style, as follows:

var o = {0:"a".1:"b".2:"c".length:3};
var iterator = Array.prototype.entries.call(o);
console.log(iterator.next().value); // [0, "a"]
console.log(iterator.next().value); // [1, "b"]
console.log(iterator.next().value); // [2, "c"]Copy the code

Since this method is based on ES6, it is not currently supported by all browsers. Here are the versions supported by each browser:

Browser Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support 38 28 (28) Unrealized. 25 7.1
find&findIndex(ES6)

The find() method is based on the ECMAScript 2015 (ES6) specification and returns the first satisfying element in the array (if any), or undefined if none.

The findIndex() method is also based on the ECMAScript 2015 (ES6) specification. It returns the index (if any) of the first element in the array that satisfies the criteria. Otherwise, it returns -1.

Syntax: arr.find(fn, thisArg), arr.findIndex(fn, thisArg)

We find that the syntax is very similar to forEach and so on. In fact, not only the syntax, find (or findIndex) is the same as forEach in terms of parameters and the considerations for using them. Therefore, the find (or findIndex) argument is omitted here. Here’s an example: 🌰 :

var array = [1.3.5.7.8.9.10];
function f(value, index, array){
  return value%2= =0; // Return an even number
}
function f2(value, index, array){
  return value > 20; // Return a number greater than 20
}
console.log(array.find(f)); / / 8
console.log(array.find(f2)); // undefined
console.log(array.findIndex(f)); / / 4
console.log(array.findIndex(f2)); // -1Copy the code

Because its duck type discrimination writing method is also consistent with forEach method, so this place is omitted.

I haven’t checked for compatibility, but the latest version of Chrome V47 and Firefox version 25 both implement them.

keys(ES6)

The keys() method is based on the ECMAScript 2015 (ES6) specification and returns an iterator for an array index. (Actual browser implementation may be adjusted)

Grammar: arr. Keys ()

var array = ["abc"."xyz"];
var iterator = array.keys();
console.log(iterator.next()); // Object {value: 0, done: false}
console.log(iterator.next()); // Object {value: 1, done: false}
console.log(iterator.next()); // Object {value: undefined, done: false}Copy the code

Index iterators contain indexes that have no corresponding elements, such as:

var array = ["abc"."xyz"];
var sparseKeys = Object.keys(array);
var denseKeys = [...array.keys()];
console.log(sparseKeys); / / / "0", "2"
console.log(denseKeys);  / / [0, 1, 2]Copy the code

Please refer to the above entries method for writing duck style.

We used array. from to generate a new Array from 0 to the specified number, which is easy to do with keys.

[...Array(10).keys()]; // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[...new Array(10).keys()]; // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]Copy the code

Because of the nature of arrays, new Array and Array treat individual numbers in the same way, both of the above are feasible.

Keys is based on ES6 and is not fully supported. Here are the versions supported by each browser:

Browser Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support 38 28 (28) Unrealized. 25 7.1
values(ES6)

The values() method is based on the ECMAScript 2015 (ES6) specification and returns an array iterator object containing the value of each index in the array. Its usage is basically the same as the above “entries” method.

Grammar: arr. Values ()

Unfortunately, no browser currently implements this method, so you’ll have to make do with it.

var array = ["abc"."xyz"];
var iterator = array.values();
console.log(iterator.next().value);//abc
console.log(iterator.next().value);//xyzCopy the code
Symbol.iterator(ES6)

This method is based on THE ECMAScript 2015 (ES6) specification and has the same functions as the VALUES method.

Grammar: arr/Symbol. The iterator ()

var array = ["abc"."xyz"];
var iterator = array[Symbol.iterator]();
console.log(iterator.next().value); // abc
console.log(iterator.next().value); // xyzCopy the code

Please refer to the above entries method for writing duck style.

Since this method is based on ES6, it is not fully supported. Here are the supported versions for each browser:

Browser Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support 38 36 (36) 1 Unrealized. 25 Unrealized.

summary

Array.prototype’s methods have a lot in common with each other. Such as:

  • All methods that insert elements, such as push and unshift, return the new length of the array.
  • All methods that delete elements, such as pop, shift, and splice, return either the deleted element or an array of deleted elements.
  • Partial traversal methods, such as forEach, every, some, filter, map, find, findIndex, are includedfunction(value,index,array){}thisArgThese two parameters.

All of Array.prototype’s methods have the magical property of duck typing. They can be used not only to handle array objects, but also array-like objects.

For example, javascript uses a natural Array like a String object. Methods like join (without changing the current object itself) are perfectly fine. The pop, push, shift, and unshift methods, for example, will raise TypeError when they operate on a String because the length of the String itself cannot be changed.

Remember, array. prototype is itself an Array, and its length is 0.

We’ll continue to explore a few things about Array in the next chapters. Thanks for reading!


If you have any questions or good ideas, please feel free to leave a comment below.

Louis

This paper links: louiszhai. Making. IO / 2017/04/28 /…

Refer to the article

  • Array.prototype
  • In Chrome, the js code array. sort sort bug is solved
  • SJ9013: array.prototype. sort If the return value is not -1, 0, or 1 after comparefn is used, the sorting results of different engines are inconsistent