数组对象原生方法
copyWithin 、fill 、pop、push、sort、reverse、shift、unshift、splice、concat、includes 、join、slice、toString、indexOf、lastIndexOf、forEach、entries 、every、some、filter、find、findIndex、keys、values、map、reduce、reduceRight
修改器方法
下面的这些方法会改变调用它们的对象自身的值
copyWithin 这是一个实验性的API,请尽量不要在生产环境中使用它
浅复制数组的一部分到同一数组中的另一个位置,并返回它,不会改变原数组的长度
/**
* arr.copyWithin(target[, start[, end]])
* @param target
* 0 为基底的索引,复制序列到该位置。如果是负数,target 将从末尾开始计算
* 如果 target 大于等于 arr.length,将会不发生拷贝。如果 target 在 start 之后,复制的序列将被修改以符合 arr.length
* @param start
* 0 为基底的索引,开始复制元素的起始位置。如果是负数,start 将从末尾开始计算
* 如果 start 被忽略,copyWithin 将会从0开始复制
* @param end
* 0 为基底的索引,开始复制元素的结束位置。copyWithin 将会拷贝到该位置,但不包括 end 这个位置的元素。如果是负数, end 将从末尾开始计算
* 如果 end 被忽略,copyWithin 方法将会一直复制至数组结尾(默认为 arr.length)
* @returns [](改变后的数组)
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
console.log(arr.copyWithin(0, 4, 5)) //[2, 5, 0, 3, 2, 7, 4, 6, 8, 9, 1]
console.log(arr.copyWithin(1, 4)) //[3, 2, 7, 4, 6, 8, 9, 1, 8, 9, 1]
fill 这是一个实验性的API,请尽量不要在生产环境中使用它
用一个固定值填充一个数组中从起始索引到终止索引内的全部元素,不包括终止索引
/**
* arr.fill(value[, start[, end]])
* @param value
* 用来填充数组元素的值
* @param start
* 起始索引,默认值为0
* @param end
* 终止索引,默认值为 this.length
* @returns [](修改后的数组)
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
console.log(arr.fill(0, 2, 4)) // [3, 5, 0, 0, 2, 7, 4, 6, 8, 9, 1]
console.log(arr.fill(5, 1)) // [3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
console.log(arr.fill(6)) // [6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6]
pop
从数组中删除最后一个元素,并返回该元素的值,此方法更改数组的长度
/**
* arr.pop()
* @returns 从数组中删除的元素(当数组为空时返回undefined)
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
console.log(arr.pop()) // 1
console.log(arr) // [3, 5, 0, 3, 2, 7, 4, 6, 8, 9]
push
将一个或多个元素添加到数组的末尾,并返回该数组的新长度
/**
* arr.push(element1, ..., elementN)
* @param elementN
* 被添加到数组末尾的元素
* @returns 当调用该方法时,新的 length 属性值将被返回
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
console.log(arr.push(7)) // 12
console.log(arr) // [3, 5, 0, 3, 2, 7, 4, 6, 8, 9, 1, 7]
console.log(arr.push(5, 8, 3)) // 15
console.log(arr) // [3, 5, 0, 3, 2, 7, 4, 6, 8, 9, 1, 7, 5, 8, 3]
sort
用原地算法对数组的元素进行排序,并返回数组。默认排序顺序是在将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的。由于它取决于具体实现,因此无法保证排序的时间和空间复杂性
/**
* arr.sort([compareFunction])
* @param compareFunction (可选)
* 用来指定按某种顺序进行排列的函数。如果省略,元素按照转换为的字符串的各个字符的Unicode位点进行排序
* firstEl 第一个用于比较的元素
* secondEl 第二个用于比较的元素
* @returns 排序后的数组。请注意,数组已原地排序,并且不进行复制
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
console.log(arr.sort()) // [0, 1, 2, 3, 3, 4, 5, 6, 7, 8, 9]
reverse
将数组中元素的位置颠倒,并返回该数组,该方法会改变原数组
/**
* arr.reverse()
* @returns 颠倒后的数组
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
console.log(arr.reverse()) // [1, 9, 8, 6, 4, 7, 2, 3, 0, 5, 3]
shift
从数组中删除第一个元素,并返回该元素的值,此方法更改数组的长度
/**
* arr.shift()
* @returns 从数组中删除的元素; 如果数组为空则返回undefined
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
console.log(arr.shift()) // 3
console.log(arr) // [5, 0, 3, 2, 7, 4, 6, 8, 9, 1]
unshift
将一个或多个元素添加到数组的开头,并返回该数组的新长度,该方法修改原有数组
/**
* arr.unshift(element1, ..., elementN)
* @param elementN
* 要添加到数组开头的元素或多个元素
* @returns 当一个对象调用该方法时,返回其 length 属性值
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
console.log(arr.unshift(4, 5)) // 13
console.log(arr) // [4, 5, 3, 5, 0, 3, 2, 7, 4, 6, 8, 9, 1]
splice
删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容,此方法会改变原数组
/**
* array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
* @param start
* 指定修改的开始位置(从0计数)。如果超出了数组的长度,则从数组末尾开始添加内容;
* 如果是负值,则表示从数组末位开始的第几位(从-1计数,这意味着-n是倒数第n个元素并且等价于array.length-n);
* 如果负数的绝对值大于数组的长度,则表示开始位置为第0位
* deleteCount (可选)
* 整数,表示要移除的数组元素的个数
* 如果 deleteCount 大于 start 之后的元素的总数,则从 start 后面的元素都将被删除(含第 start 位)
* 如果 deleteCount 被省略了,或者它的值大于等于array.length - start(也就是说,如果它大于或者等于start之后的所有元素的数量),那么start之后数组的所有元素都会被删除
* 如果 deleteCount 是 0 或者负数,则不移除元素。这种情况下,至少应添加一个新元素
* item1, item2, ... (可选)
* 要添加进数组的元素,从start 位置开始。如果不指定,则 splice() 将只删除数组元素
* @returns 由被删除的元素组成的一个数组。如果只删除了一个元素,则返回只包含一个元素的数组。如果没有删除元素,则返回空数组
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
console.log(arr.splice(1, 0, 8)) // []
console.log(arr) // [3, 8, 5, 0, 3, 2, 7, 4, 6, 8, 9, 1]
console.log(arr.splice(4, 2, 7, 2)) // [3, 2]
console.log(arr) // [3, 8, 5, 0, 7, 2, 7, 4, 6, 8, 9, 1]
访问方法
下面的这些方法绝对不会改变调用它们的对象的值,只会返回一个新的数组或者返回一个其它的期望值
concat
用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组
/**
* var new_array = old_array.concat(value1[, value2[, ...[, valueN]]])
* @param valueN (可选)
* 数组和/或值,将被合并到一个新的数组中。如果省略了所有 valueN 参数,则 concat 会返回调用此方法的现存数组的一个浅拷贝
* @returns 新的 Array 实例
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
const tempArr = [7, 3, 8, 5]
const tempNewArr = arr.concat(tempArr)
const newArray = arr.concat([7, 3, 8, 5])
console.log(tempNewArr) // [3, 5, 0, 3, 2, 7, 4, 6, 8, 9, 1, 7, 3, 8, 5]
console.log(newArray) // [3, 5, 0, 3, 2, 7, 4, 6, 8, 9, 1, 7, 3, 8, 5]
includes 这是一个实验性的API,请尽量不要在生产环境中使用它
判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false
/**
* arr.includes(valueToFind[, fromIndex])
* @param valueToFind
* 需要查找的元素值
* @param fromIndex (可选)
* 从fromIndex 索引处开始查找 valueToFind。
* 如果为负值,则按升序从 array.length + fromIndex 的索引开始搜
* (即使从末尾开始往前跳 fromIndex 的绝对值个索引,然后往后搜寻),默认为 0
* @returns 返回一个布尔值 Boolean ,如果在数组中找到了(如果传入了 fromIndex ,表示在 fromIndex 指定的索引范围中找到了)则返回 true
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
console.log(arr.includes(2)) // true
console.log(arr.includes(11)) // false
join
将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。如果数组只有一个项目,那么将返回该项目而不使用分隔符
/**
* arr.join([separator])
* @param separator (可选)
* 指定一个字符串来分隔数组的每个元素。
* 如果需要,将分隔符转换为字符串。
* 如果缺省该值,数组元素用逗号(,)分隔。
* 如果separator是空字符串(""),则所有元素之间都没有任何字符
* @returns 返回一个布尔值 Boolean ,如果在数组中找到了(如果传入了 fromIndex ,表示在 fromIndex 指定的索引范围中找到了)则返回 true
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
console.log(arr.join()) // 3,5,0,3,2,7,4,6,8,9,1
console.log(arr.join('')) // 35032746891
console.log(arr.join('-')) // 3-5-0-3-2-7-4-6-8-9-1
slice
返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end),原始数组不会被改变
/**
* arr.slice([begin[, end]])
* @param begin (可选)
* 提取起始处的索引(从 0 开始),从该索引开始提取原数组元素。
* 如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取,slice(-2) 表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。
* 如果省略 begin,则 slice 从索引 0 开始。
* 如果 begin 大于原数组的长度,则会返回空数组
* @param end (可选)
* 提取终止处的索引(从 0 开始),在该索引处结束提取原数组元素。slice 会提取原数组中索引从 begin 到 end 的所有元素(包含 begin,但不包含 end
* slice(1,4) 会提取原数组中从第二个元素开始一直到第四个元素的所有元素 (索引为 1, 2, 3的元素)
* 如果该参数为负数, 则它表示在原数组中的倒数第几个元素结束抽取。
* slice(-2,-1) 表示抽取了原数组中的倒数第二个元素到最后一个元素(不包含最后一个元素,也就是只有倒数第二个元素)
* 如果 end 被省略,则 slice 会一直提取到原数组末尾
* 如果 end 大于数组的长度,slice 也会一直提取到原数组末尾
* @returns 一个含有被提取元素的新数组
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
console.log(arr.slice(2)) // [0, 3, 2, 7, 4, 6, 8, 9, 1]
console.log(arr.slice(2, 4)) // [0, 3]
console.log(arr.slice(1, 15)) // [5, 0, 3, 2, 7, 4, 6, 8, 9, 1]
toString
返回一个字符串,表示指定的数组及其元素
/**
* arr.toString()
* @returns 一个表示指定的数组及其元素的字符串
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
console.log(arr.toString()) // 3,5,0,3,2,7,4,6,8,9,1
indexOf
返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1
/**
* arr.indexOf(searchElement[, fromIndex])
* @param searchElement
* 要查找的元素
* @param fromIndex (可选)
* 开始查找的位置。
* 如果该索引值大于或等于数组长度,意味着不会在数组里查找,返回-1。
* 如果参数中提供的索引值是一个负值,则将其作为数组末尾的一个抵消,即-1表示从最后一个元素开始查找,-2表示从倒数第二个元素开始查找 ,以此类推。
* 注意:
* 如果参数中提供的索引值是一个负值,并不改变其查找顺序,查找顺序仍然是从前向后查询数组。
* 如果抵消后的索引值仍小于0,则整个数组都将会被查询。其默认值为0
* @returns 首个被找到的元素在数组中的索引位置; 若没有找到则返回 -1
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
console.log(arr.indexOf(2)) // 4
console.log(arr.indexOf(10)) // -1
lastIndexOf
返回指定元素(也即有效的 JavaScript 值或变量)在数组中的最后一个的索引,如果不存在则返回 -1。从数组的后面向前查找,从 fromIndex 处开始
/**
* arr.lastIndexOf(searchElement[, fromIndex])
* @param searchElement
* 要查找的元素
* @param fromIndex (可选)
* 从此位置开始逆向查找。默认为数组的长度减 1(arr.length - 1),即整个数组都被查找。
* 如果该值大于或等于数组的长度,则整个数组会被查找。
* 如果为负值,将其视为从数组末尾向前的偏移。
* 即使该值为负,数组仍然会被从后向前查找。
* 如果该值为负时,其绝对值大于数组长度,则方法返回 -1,即数组不会被查找
* @returns 数组中该元素最后一次出现的索引,如未找到返回-1
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
console.log(arr.lastIndexOf(3)) // 3
console.log(arr.lastIndexOf(10)) // -1
迭代方法
在下面的众多遍历方法中,有很多方法都需要指定一个回调函数作为参数。在每一个数组元素都分别执行完回调函数之前,数组的length属性会被缓存在某个地方,所以,如果你在回调函数中为当前数组添加了新的元素,那么那些新添加的元素是不会被遍历到的。此外,如果在回调函数中对当前数组进行了其它修改,比如改变某个元素的值或者删掉某个元素,那么随后的遍历操作可能会受到未预期的影响。总之,不要尝试在遍历过程中对原数组进行任何修改,虽然规范对这样的操作进行了详细的定义,但为了可读性和可维护性,请不要这样做
forEach
方法对数组的每个元素执行一次给定的函数
/**
* arr.forEach(callback(currentValue [, index [, array]])[, thisArg])
* @param callback
* 为数组中每个元素执行的函数,该函数接收一至三个参数:
* currentValue 数组中正在处理的当前元素
* index(可选) 数组中正在处理的当前元素的索引
* array(可选) forEach() 方法正在操作的数组
* @param thisArg(可选)
* 可选参数。当执行回调函数 callback 时,用作 this 的值
* @returns undefined
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
arr.forEach(element => console.log(element))
// 3
// 5
// 0
// 3
// 2
// 7
// 4
// 6
// 8
// 9
// 1
entries 这是一个实验性的API,请尽量不要在生产环境中使用它
返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对
/**
* arr.entries()
* @returns
* 一个新的 Array 迭代器对象。Array Iterator是对象,
* 它的原型(__proto__:Array Iterator)上有一个next方法,可用用于遍历迭代器取得原数组的[key,value]
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
const iterator1 = arr.entries();
console.log(iterator1.next().value) // [0, 3]
console.log(iterator1.next().value) // [1, 5]
console.log(iterator1.next().value) // [2, 0]
every
测试一个数组内的所有元素是否都能通过某个指定函数的测试,它返回一个布尔值
/**
* arr.every(callback(element[, index[, array]])[, thisArg])
* @param callback
* 用来测试每个元素的函数,它可以接收三个参数:
* element 用于测试的当前值
* index(可选) 用于测试的当前值的索引
* array(可选) 调用 every 的当前数组
* @param thisArg(可选)
* 执行 callback 时使用的 this 值
* @returns 如果回调函数的每一次返回都为 truthy 值,返回 true ,否则返回 false
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
console.log(arr.every(value => value < 10)) // true
console.log(arr.every(value => value / 2 === 0)) // false
some
测试数组中是不是至少有1个元素通过了被提供的函数测试。它返回的是一个Boolean类型的值
/**
* arr.some(callback(element[, index[, array]])[, thisArg])
* @param callback
* 用来测试每个元素的函数,接受三个参数:
* element 数组中正在处理的元素
* index (可选) 数组中正在处理的元素的索引值
* array (可选) some()被调用的数组
* @param thisArg(可选)
* 执行 callback 时使用的 this 值
* @returns 数组中有至少一个元素通过回调函数的测试就会返回true;所有元素都没有通过回调函数的测试返回值才会为false
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
console.log(arr.some(value => value > 8)) // true
console.log(arr.some(value => value / 2 === 0)) // true
console.log(arr.some(value => value <-1)) // false
filter
创建一个新数组, 其包含通过所提供函数实现的测试的所有元素
/**
* var newArray = arr.filter(callback(element[, index[, array]])[, thisArg])
* @param callback
* 用来测试数组的每个元素的函数。返回 true 表示该元素通过测试,保留该元素,false 则不保留,它接受以下三个参数:
* element 数组中当前正在处理的元素
* index (可选) 正在处理的元素在数组中的索引
* array (可选) 调用了 filter 的数组本身
* @param thisArg(可选)
* 执行 callback 时,用于 this 的值
* @returns 一个新的、由通过测试的元素组成的数组,如果没有任何数组元素通过测试,则返回空数组
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
const result = arr.filter(value => value % 2 === 0)
console.log(result) // [0, 2, 4, 6, 8]
find这是一个实验性的API,请尽量不要在生产环境中使用它
返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined
/**
* arr.find(callback[, thisArg])
* @param callback
* 在数组每一项上执行的函数,接收 3 个参数:
* element 当前遍历到的元素
* index (可选) 当前遍历到的索引
* array (可选) 数组本身
* @param thisArg(可选)
* 执行回调时用作this 的对象
* @returns 数组中第一个满足所提供测试函数的元素的值,否则返回 undefined
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
const result = arr.find(value => value > 5)
console.log(result) // 7
findIndex这是一个实验性的API,请尽量不要在生产环境中使用它
返回数组中满足提供的测试函数的第一个元素的索引。若没有找到对应元素则返回-1
/**
* arr.findIndex(callback[, thisArg])
* @param callback
* 针对数组中的每个元素, 都会执行该回调函数, 执行时会自动传入下面三个参数:
* element 当前元素
* index (可选) 当前元素的索引
* array (可选) 调用findIndex的数组
* @param thisArg(可选)
* 执行callback时作为this对象的值.
* @returns 数组中通过提供测试函数的第一个元素的索引。否则,返回-1
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
const result = arr.findIndex(value => value > 5)
console.log(result) // 5
keys 这是一个实验性的API,请尽量不要在生产环境中使用它
返回一个包含数组中每个索引键的Array Iterator对象
/**
* arr.keys()
* @returns 一个新的 Array 迭代器对象
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
const iterator = arr.keys();
for (const key of iterator) {
console.log(key);
}
// 3
// 5
// 0
// 3
// 2
// 7
// 4
// 6
// 8
// 9
// 1
values 这是一个实验性的API,请尽量不要在生产环境中使用它
返回一个新的 Array Iterator 对象,该对象包含数组每个索引的值
/**
* arr.values()
* @returns 一个新的 Array 迭代对象
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
const iterator = arr.values();
for (const values of iterator) {
console.log(values);
}
// 0
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
// 10
map
创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值
/**
* var new_array = arr.map(function callback(currentValue[, index[, array]]) {
// Return element for new_array
}[, thisArg])
* @param callback
* 生成新数组元素的函数,使用三个参数:
* currentValue callback 数组中正在处理的当前元素
* index (可选) callback 数组中正在处理的当前元素的索引
* array (可选) map 方法调用的数组
* @param thisArg(可选)
* 执行 callback 函数时值被用作this
* @returns 一个由原数组每个元素执行回调函数的结果组成的新数组
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
const result = arr.map(value => value * 2)
console.log(result) // [6, 10, 0, 6, 4, 14, 8, 12, 16, 18, 2]
reduce
对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值
/**
* arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
* @param callback
* 执行数组中每个值 (如果没有提供 initialValue则第一个值除外)的函数,包含四个参数:
* accumulator 累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或initialValue(见于下方)
* currentValue 数组中正在处理的元素
* index (可选) 数组中正在处理的当前元素的索引。 如果提供了initialValue,则起始索引号为0,否则从索引1起始
* array (可选) 调用reduce()的数组
* @param initialValue(可选)
* 作为第一次调用 callback函数时的第一个参数的值。
* 如果没有提供初始值,则将使用数组中的第一个元素。
* 在没有初始值的空数组上调用 reduce 将报错
* @returns 函数累计处理的结果
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
const reducer = (accumulator, currentValue) => accumulator + currentValue;
console.log(arr.reduce(reducer)) // 48
console.log(arr.reduce(reducer, 10)) // 58
reduceRight
接受一个函数作为累加器(accumulator)和数组的每个值(从右到左)将其减少为单个值
/**
* arr.reduceRight(callback(accumulator, currentValue[, index[, array]])[, initialValue])
* @param callback
* 一个回调函数,用于操作数组中的每个元素,它可接受四个参数:
* accumulator
* 累加器:
* 上一次调用回调函数时,回调函数返回的值。
* 首次调用回调函数时,如果 initialValue 存在,累加器即为 initialValue,
* 否则须为数组中的最后一个元素(详见下方 initialValue 处相关说明)
* currentValue 当前元素:当前被处理的元素
* index (可选) 数组中当前被处理的元素的索引
* array (可选) 调用 reduceRight() 的数组
* @param initialValue(可选)
* 首次调用 callback 函数时,累加器 accumulator 的值。
* 如果未提供该初始值,则将使用数组中的最后一个元素,并跳过该元素。
* 如果不给出初始值,则需保证数组不为空。
* 否则,在空数组上调用 reduce 或 reduceRight 且未提供初始值
* (例如 [].reduce( (acc, cur, idx, arr) => {} ) )的话,
* 会导致类型错误 TypeError: reduce of empty array with no initial value)
* @returns 执行之后的返回值
**/
const arr = [3, 5, 0, 3, 2, 7, 4 , 6, 8, 9, 1]
const temp = [9, 8]
const result = [arr, temp].reduceRight((accumulator, currentValue) => accumulator.concat(currentValue))
console.log(result) // [9, 8, 3, 5, 0, 3, 2, 7, 4, 6, 8, 9, 1]