Skip to main content

数组的方法

Array.prototype.values()

返回一个新的 Array Iterator 对象,该对象包含数组每个索引的值

arr.values()

    1. 使用 for...of 循环进行迭代
let arr = ['w', 'y', 'k', 'o', 'p'];
let eArr = arr.values();

for (let letter of eArr) {
console.log(letter);
} //"w" "y "k" "o" "p"
    1. 使用 .next() 迭代
var arr = ['a', 'b', 'c', 'd', 'e'];
var iterator = arr.values();
iterator.next(); // Object { value: "a", done: false }
iterator.next().value; // "b"
iterator.next()['value']; // "c"
iterator.next(); // Object { value: "d", done: false }
iterator.next(); // Object { value: "e", done: false }
iterator.next(); // Object { value: undefined, done: true }
iterator.next().value; // undefined
    1. 一次性:数组迭代器是一次性的,或者说临时对象

      当 next().done=true 或 currentIndex>length 时, for..of 循环结束 。

var arr = ['a', 'b', 'c', 'd', 'e'];
var iterator = arr.values();
for (let letter of iterator) {
console.log(letter);
}
//"a" "b" "c" "d"
for (let letter of iterator) {
console.log(letter);
}
// undefined
    1. 数组迭代器中存储的是原数组的地址,而不是数组元素值。
var arr = ['a', 'b', 'c', 'd', 'e'];
var iterator = arr.values();
console.log(iterator); // Array Iterator { }
iterator.next().value; // "a"
arr[1] = 'n';
iterator.next().value; // "n"

Array.prototype.values 是 Array.prototype[Symbol.iterator] 的默认实现。 Array.prototype.values === Array.prototype[Symbol.iterator] // true

Array.prototype[@@iterator] ()

arr[Symbol.iterator] ()

function logIterable(it) {
var iterator = it[Symbol.iterator]();
// 浏览器必须支持 for...of 循环
for (let letter of iterator) {
console.log(letter);
}
}

// Array
logIterable(['a', 'b', 'c']);
// a
// b
// c

// string
logIterable('abc');
// a
// b
// c

Array.prototype.concat()

合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。

var alpha = ['a', 'b', 'c'];
var numeric = [1, 2, 3];

alpha.concat(numeric);
//
var alpha = ['a', 'b', 'c'];

var alphaNumeric = alpha.concat(1, [2, 3]);

console.log(alphaNumeric);
// results in ['a', 'b', 'c', 1, 2, 3]

Array.prototype.copyWithin()

复制数组的一部分到同一数组中的另一个位置,并返回它,不会改变原数组的长度。

arr.copyWithin(target[, start[, end]])

  • target 复制到哪里, 1.大于 arr.length 不拷贝; 2.target 在 start 之后
[1, 2, 3, 4, 5].copyWithin(-2)
// [1, 2, 3, 1, 2]

[1, 2, 3, 4, 5].copyWithin(0, 3)
// [4, 5, 3, 4, 5]

[1, 2, 3, 4, 5].copyWithin(0, 3, 4)
// [4, 2, 3, 4, 5]

[1, 2, 3, 4, 5].copyWithin(-2, -3, -1)
// [1, 2, 3, 3, 4]

[].copyWithin.call({length: 5, 3: 1}, 0, 3);
// {0: 1, 3: 1, length: 5}

// ES2015 Typed Arrays are subclasses of Array
var i32a = new Int32Array([1, 2, 3, 4, 5]);

i32a.copyWithin(0, 2);
// Int32Array [3, 4, 5, 4, 5]

// On platforms that are not yet ES2015 compliant:
[].copyWithin.call(new Int32Array([1, 2, 3, 4, 5]), 0, 3, 4);
// Int32Array [4, 2, 3, 4, 5]

Array.prototype.entries()

新的 Array Iterator 对象,该对象包含数组中每个索引的键/值对。

var arr = ['a', 'b', 'c'];
var iterator = arr.entries();
console.log(iterator);

/*Array Iterator {}
__proto__:Array Iterator
next:ƒ next()
Symbol(Symbol.toStringTag):"Array Iterator"
__proto__:Object
*/
console.log(iterator.next());

/*{value: Array(2), done: false}
done:false
value:(2) [0, "a"]
__proto__: Object
*/
// iterator.next()返回一个对象,对于有元素的数组,
// 是next{ value: Array(2), done: false };
// next.done 用于指示迭代器是否完成:在每次迭代时进行更新而且都是false,
// 直到迭代器结束done才是true。
// next.value是一个["key","value"]的数组,是返回的迭代器中的元素值。
  • 二维数组排序
function sortArr(arr) {
var goNext = true;
var entries = arr.entries();
while (goNext) {
var result = entries.next();
if (result.done !== true) {
result.value[1].sort((a, b) => a - b);
goNext = true;
} else {
goNext = false;
}
}
return arr;
}

var arr = [
[1, 34],
[456, 2, 3, 44, 234],
[4567, 1, 4, 5, 6],
[34, 78, 23, 1],
];
sortArr(arr);

/*(4) [Array(2), Array(5), Array(5), Array(4)]
0:(2) [1, 34]
1:(5) [2, 3, 44, 234, 456]
2:(5) [1, 4, 5, 6, 4567]
3:(4) [1, 23, 34, 78]
length:4
__proto__:Array(0)
*/

Array.prototype.every()

判断数组内所有元素是否都满足该指定函数,返回 boolean

every 方法为数组中的每个元素执行一次 callback 函数,直到它找到一个会使 callback 返回 falsy 的元素。如果发现了一个这样的元素,every 方法将会立即返回 false。否则,callback 为每一个元素返回 true,every 就会返回 true。

Array.prototype.fill()

arr.fill(value[, start[, end]])

用一个固定值填充一个数组中从起始索引到终止索引内的全部元素,不包括终止索引

[1, 2, 3].fill(4); // [4, 4, 4]
[1, 2, 3].fill(4, 1); // [1, 4, 4]
[1, 2, 3].fill(4, 1, 2); // [1, 4, 3]
[1, 2, 3].fill(4, 1, 1); // [1, 2, 3]
[1, 2, 3].fill(4, 3, 3); // [1, 2, 3]
[1, 2, 3].fill(4, -3, -2); // [4, 2, 3]
[1, 2, 3].fill(4, NaN, NaN); // [1, 2, 3]
[1, 2, 3].fill(4, 3, 5); // [1, 2, 3]
Array(3).fill(4); // [4, 4, 4]
[].fill.call({ length: 3 }, 4); // {0: 4, 1: 4, 2: 4, length: 3}

// Objects by reference.
var arr = Array(3).fill({}); // [{}, {}, {}];
// 需要注意如果fill的参数为引用类型,会导致都执行都一个引用类型
// 如 arr[0] === arr[1] 为true
arr[0].hi = 'hi'; // [{ hi: "hi" }, { hi: "hi" }, { hi: "hi" }]

Array.prototype.filter()

filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。

var newArray = arr.filter[callback(element[, index[, array]]](, thisArg))

Array.prototype.find()

返回数组中满足提供的测试函数的第一个元素的值。

[1, 4, -5, 10].find((n) => n < 0);
// -5

Array.prototype.findIndex()

arr.findIndex(callback[, thisArg])

第一个元素的索引。若没有找到对应元素则返回-1。

[1, 5, 10, 15].find(function (value, index, arr) {
return value > 9;
}); // 10

Array.prototype.flat()

var newArray = arr.flat([depth])

  • depth 提取嵌套数组的结构深度
// 使用 reduce、concat 和递归展开无限多层嵌套的数组
var arr1 = [1, 2, 3, [1, 2, 3, 4, [2, 3, 4]]];

function flatDeep(arr, d = 1) {
return d > 0
? arr.reduce((acc, val) => acc.concat(Array.isArray(val) ? flatDeep(val, d - 1) : val), [])
: arr.slice();
}

flatDeep(arr1, Infinity);

Array.prototype.flatMap()

var new_array = arr.flatMap(function callback(currentValue[, index[, array]]) {

// return element for new_array

}[, thisArg]) 首先使用映射函数映射每个元素,然后将结果压缩成一个新数组,它与 map 连着深度值为 1 的 flat 几乎相同,但 flatMap 通常在合并成一种方法的效率稍微高一些。

  • 给定一个数组,移除负数,同时把奇数分成一个偶数和 1
const a = [5, 4, -3, 20, 17, -33, -4, 18];

a.flatMap((n) => (n < 0 ? [] : n % 2 == 0 ? [n] : [n - 1, 1]));
//[4, 1, 4, 20, 16, 1, 18]

Array.prototype.forEach()

arr.forEach[callback(currentValue [, index [, array]]](, thisArg))

forEach() 方法按升序为数组中含有效值的每一项执行一次 callback 函数,那些已删除或者未初始化的项将被跳过(例如在稀疏数组上)

  1. 遍历范围在第一次调用 callback 前就会确定,调用 forEach 后添加到数组中项不会被 callback 访问到
const a = [1, 2, 3, 4, 5, 6];
a.forEach((item, index, arr) => {
console.log('item => ', item);
a[index + 6] = a[index] * +10;
arr[index + 6] = arr[index] * +10;
});
// 1,2,3,4,5,6
  1. 如果存在已经改变的值,则传递给 callback 的值是 forEach 遍历他们那一刻的值
const a = [1, 2, 3, 4, 5, 6];
a.forEach((item, index, arr) => {
console.log('item => ', item);
if (index < arr.length - 1) {
arr[index + 1] = arr[index + 1] * 2;
}
});
// 1,4,6,8,10,12
//a = [1, 4, 6, 8, 10, 12]
  1. 已删除的项不会被遍历
const words = ['one', 'two', 'three', 'four'];
words.forEach((word, index) => {
console.log('word-index:', word, index);
if (word === 'two') {
words.shift();
}
});
//one
//two
//four
// word=["two", "three", "four"]
  1. forEach 为每个元素执行一次 callback,与 map 和 reduce 不同的是,它总是返回返回 undefined. 并且不可链式调用

  2. forEach 被调用时不会改变原数组(直接改变),但是那个对象可能会被 callback 改变

稀疏数组

function logArrayElements(element, index, array) {
console.log('a[' + index + '] = ' + element);
}
// 注意索引 2 被跳过了,因为在数组的这个位置没有项
[2, 5, , 9].forEach(logArrayElements);
// logs:
// a[0] = 2
// a[1] = 5
// a[3] = 9

针对 promise 或 async 函数的使用备注

let ratings = [5, 4, 5];

let sum = 0;

let sumFunction = async function (a, b) {
return a + b;
};

ratings.forEach(async function (rating) {
sum = await sumFunction(sum, rating);
});

console.log(sum);
// 期望: 14
// 实际: 0
// 等会呢: 5

Array.from()

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

从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例

Array.from('foo');
// [ "f", "o", "o" ]

const set = new Set(['foo', 'bar', 'baz', 'foo']);
Array.from(set);
// [ "foo", "bar", "baz" ]

const map = new Map([
[1, 2],
[2, 4],
[4, 8],
]);
Array.from(map);
// [[1, 2], [2, 4], [4, 8]]

const mapper = new Map([
['1', 'a'],
['2', 'b'],
]);
Array.from(mapper.values());
// ['a', 'b'];

Array.from(mapper.keys());
// ['1', '2'];

// 从类数组对象(arguments)生成数组
function f() {
return Array.from(arguments);
}
f(1, 2, 3);
// [ 1, 2, 3 ]

Array.from({ length: 5 }, (v, i) => i);
// [0, 1, 2, 3, 4]

// Sequence generator function (commonly referred to as "range", e.g. Clojure, PHP etc)
const range = (start, stop, step) =>
Array.from({ length: (stop - start) / step + 1 }, (_, i) => start + i * step);

// Generate numbers range 0..4
range(0, 4, 1);
// [0, 1, 2, 3, 4]

// Generate numbers range 1..10 with step of 2
range(1, 10, 2);
// [1, 3, 5, 7, 9]

// Generate the alphabet using Array.from making use of it being ordered as a sequence
range('A'.charCodeAt(0), 'Z'.charCodeAt(0), 1).map((x) => String.fromCharCode(x));
// ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]

Array.isArray()

Array.isArray(obj)

Array.of()

Array.of(element0[, element1[, ...[, elementN]]])

创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。

Array.of(7); // [7]
Array.of(1, 2, 3); // [1, 2, 3]

Array(7); // [ , , , , , , ]
Array(1, 2, 3); // [1, 2, 3]

Array.prototype.pop()

删除最后一个元素,并返回该元素的值。此方法更改数组的长度。

Array.prototype.push()

一个或多个元素添加到数组的末尾,并返回该数组的新长度。

Array.prototype.reduce()

arr.reduce[callback(accumulator, currentValue[, index[, array]]](, initialValue)) 如果没有提供 initialValue,reduce 会从索引 1 的地方开始执行 callback 方法,跳过第一个索引。如果提供 initialValue,从索引 0 开始。

  • 数组去重 如果你正在使用一个可以兼容 Set 和 Array.from() 的环境, 你可以使用 let orderedArray = Array.from(new Set(myArray)); 来获得一个相同元素被移除的数组。
let myArray = ['a', 'b', 'a', 'b', 'c', 'e', 'e', 'c', 'd', 'd', 'd', 'd'];
let myOrderedArray = myArray.reduce(function (accumulator, currentValue) {
if (accumulator.indexOf(currentValue) === -1) {
accumulator.push(currentValue);
}
return accumulator;
}, []);

console.log(myOrderedArray);
let arr = [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4];
let result = arr.sort().reduce((init, current) => {
if (init.length === 0 || init[init.length - 1] !== current) {
init.push(current);
}
return init;
}, []);
console.log(result); //[1,2,3,4,5]
  • 按顺序运行 Promise
/**
* Runs promises from array of functions that can return promises
* in chained manner
*
* @param {array} arr - promise arr
* @return {Object} promise object
*/
function runPromiseInSequence(arr, input) {
return arr.reduce(
(promiseChain, currentFunction) => promiseChain.then(currentFunction),
Promise.resolve(input)
);
}

// promise function 1
function p1(a) {
return new Promise((resolve, reject) => {
resolve(a * 5);
});
}

// promise function 2
function p2(a) {
return new Promise((resolve, reject) => {
resolve(a * 2);
});
}

// function 3 - will be wrapped in a resolved promise by .then()
function f3(a) {
return a * 3;
}

// promise function 4
function p4(a) {
return new Promise((resolve, reject) => {
resolve(a * 4);
});
}

const promiseArr = [p1, p2, f3, p4];
runPromiseInSequence(promiseArr, 10).then(console.log); // 1200
  • 功能型函数管道
// Building-blocks to use for composition
const double = (x) => x + x;
const triple = (x) => 3 * x;
const quadruple = (x) => 4 * x;

// Function composition enabling pipe functionality
const pipe =
(...functions) =>
(input) =>
functions.reduce((acc, fn) => fn(acc), input);

// Composed functions for multiplication of specific values
const multiply6 = pipe(double, triple);
const multiply9 = pipe(triple, triple);
const multiply16 = pipe(quadruple, quadruple);
const multiply24 = pipe(double, triple, quadruple);

// Usage
multiply6(6); // 36
multiply9(9); // 81
multiply16(16); // 256
multiply24(10); // 240

Array.prototype.reduceRight()

方法接受一个函数作为累加器(accumulator)和数组的每个值(从右到左)将其减少为单个值。

arr.reduceRight[callback(accumulator, currentValue[, index[, array]]](, initialValue

Array.prototype.reverse()

方法将数组中元素的位置颠倒,并返回该数组。数组的第一个元素会变成最后一个,数组的最后一个元素变成第一个。该方法会改变原数组。

Array.prototype.shift()

shift() 方法从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。

Array.prototype.unshift()

将一个或多个元素添加到数组的开头,并返回该数组的新长度(该方法修改原有数组)

Array.prototype.slice()

arr.slice([begin[, end]])

截取数组,浅拷贝

// 使用 slice 方法从 myCar 中创建一个 newCar。
var myHonda = { color: 'red', wheels: 4, engine: { cylinders: 4, size: 2.2 } };
var myCar = [myHonda, 2, 'cherry condition', 'purchased 1997'];
var newCar = myCar.slice(0, 2);

// 输出 myCar、newCar 以及各自的 myHonda 对象引用的 color 属性。
console.log(' myCar = ' + JSON.stringify(myCar));
console.log('newCar = ' + JSON.stringify(newCar));
console.log(' myCar[0].color = ' + JSON.stringify(myCar[0].color));
console.log('newCar[0].color = ' + JSON.stringify(newCar[0].color));

// 改变 myHonda 对象的 color 属性.
myHonda.color = 'purple';
console.log('The new color of my Honda is ' + myHonda.color);

//输出 myCar、newCar 中各自的 myHonda 对象引用的 color 属性。
console.log(' myCar[0].color = ' + myCar[0].color);
console.log('newCar[0].color = ' + newCar[0].color);
  • 类数组(Array-like)对象
function list() {
return Array.prototype.slice.call(arguments);
}

var list1 = list(1, 2, 3); // [1, 2, 3]

Array.prototype.some()

arr.some[callback(element[, index[, array]]](, thisArg))

至少有一个满足

Array.prototype.sort()

方法用原地算法对数组的元素进行排序,并返回数组。默认排序顺序是在将元素转换为字符串,然后比较它们的 UTF-16 代码单元值序列时构建的

排序啊 啊啊啊

Array.prototype.splice()

删除替换数组,返回被修改的内容,会改变原数组 array.splice(start[, deleteCount[, item1[, item2[, ...]]]])

Array.prototype.toLocaleString()

字符串表示数组中的元素。数组中的元素将使用各自的 toLocaleString 方法转成字符串,这些字符串将使用一个特定语言环境的字符串(例如一个逗号 ",")隔开。

var prices = ['¥7', 500, 8123, 12];
prices.toLocaleString('zh-Hans-CN', { style: 'currency', currency: 'CNY' });

// "¥7,¥500,¥8,123,¥12"

ES6 的扩展

1.扩展运算符

扩展运算符,三个点(...), rest 参数的逆运算

// ES5 的写法
Math.max.apply(null, [14, 3, 77]);

// ES6 的写法
Math.max(...[14, 3, 77]);

// 等同于
Math.max(14, 3, 77);

2.复制数组

//es5
const a1 = [1, 2];
const a2 = a1.concat();

a2[0] = 2;
a1; // [1, 2]
//es6
const a1 = [1, 2];
// 写法一
const a2 = [...a1];
// 写法二
const [...a2] = a1;

对于没有部署 Iterator 接口的类数组的对象,扩展运算符无法将其转为真正的数组

let arrayLike = {
0: 'a',
1: 'b',
2: 'c',
length: 3,
};

// TypeError: Cannot spread non-iterable object.
let arr = [...arrayLike];

类数组转数组????

Map 和 Set 结构,Generator 函数

扩展运算符内部调用的是数据结构的 Iterator 接口,因此只要具有 Iterator 接口的对象,都可以使用扩展运算符,比如 Map 结构。

let map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);

let arr = [...map.keys()]; // [1, 2, 3]

const go = function* () {
yield 1;
yield 2;
yield 3;
};

[...go()]; // [1, 2, 3]

2. Array.from()

Array.from 方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)。

let arrayLike = {
0: 'a',
1: 'b',
2: 'c',
length: 3,
};

// ES5的写法
// Array.prototype.slice
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

///
// NodeList对象
let ps = document.querySelectorAll('p');
Array.from(ps).filter((p) => {
return p.textContent.length > 100;
});

// arguments对象
function foo() {
var args = Array.from(arguments);
// ...
}

entries(),keys()和 values()

它们都返回一个遍历器对象 和对象 Object.xxx 方法不一样

for (let index of ['a', 'b'].keys()) {
console.log(index);
}
// 0
// 1

for (let elem of ['a', 'b'].values()) {
console.log(elem);
}
// 'a'
// 'b'

for (let [index, elem] of ['a', 'b'].entries()) {
console.log(index, elem);
}
// 0 "a"
// 1 "b"
let letter = ['a', 'b', 'c'];
let entries = letter.entries();
console.log(entries.next().value); // [0, 'a']
console.log(entries.next().value); // [1, 'b']
console.log(entries.next().value); // [2, 'c']

数组的空位

ES5 对空位的处理,已经很不一致了,大多数情况下会忽略空位。

  • forEach(), filter(), reduce(), every() 和 some()都会跳过空位。
  • map()会跳过空位,但会保留这个值
  • join()和 toString()会将空位视为 undefined,而 undefined 和 null 会被处理成空字符串。
// forEach方法
[,'a'].forEach((x,i) => console.log(i)); // 1

// filter方法
['a',,'b'].filter(x => true) // ['a','b']

// every方法
[,'a'].every(x => x==='a') // true

// reduce方法
[1,,2].reduce((x,y) => x+y) // 3

// some方法
[,'a'].some(x => x !== 'a') // false

// map方法
[,'a'].map(x => 1) // [,1]
let a=new Array(3).map((i,index)=>index) //[,,]

// join方法
[,'a',undefined,null].join('#') // "#a##"

// toString方法
[,'a',undefined,null].toString() // ",a,,"

ES6 则是明确将空位转为 undefined。就是不会忽略空位

Array.from(['a',,'b'])
// [ "a", undefined, "b" ]
[...['a',,'b']]
// [ "a", undefined, "b" ]

[,'a','b',,].copyWithin(2,0) // [,"a",,"a"]

new Array(3).fill('a') // ["a","a","a"]

let arr = [, ,];
for (let i of arr) {
console.log(1);
}
// 1
// 1
//数组arr有两个空位,for...of并没有忽略它们。如果改成map方法遍历,空位是会跳过的。

// entries()
[...[,'a'].entries()] // [[0,undefined], [1,"a"]]

// keys()
[...[,'a'].keys()] // [0,1]

// values()
[...[,'a'].values()] // [undefined,"a"]

// find()
[,'a'].find(x => true) // undefined

// findIndex()
[,'a'].findIndex(x => true) // 0

Array.prototype.sort() 的排序稳定性

插入排序、合并排序、冒泡排序等都是稳定的,堆排序、快速排序等是不稳定的。

let arr = ['abb', 'aaa', 'ccc', 'bccc', 'bbb'];
arr.sort((a, b) => a.codePointAt(0) - b.codePointAt(0));
///['abb', 'aaa', 'bccc', 'bbb', 'ccc']

x

数组乱序

// 著名的Fisher–Yates shuffle 洗牌算法
function shuffle(arr) {
let m = arr.length;
while (m > 1) {
let index = parstInt(Math.random() * m--);
[arr[index], arr[m]] = [arr[m], arr[index]];
}
return arr;
}

// 取巧的一种算法,但是每个位置乱序的概率不同
function mixArr(arr) {
return arr.sort(() => {
return Math.random() - 0.5;
});
}

数组去重

const arr = [1, 2, 2, 2, 3, 3, 1, 2, 3, 1];
const res = arr.filter((item, index, ary) => {
return ary.indexOf(item) === index;
});
console.log(res);

插入排序

function sort1(ary) {
const newAry = [ary[0]];
for (let i = 1; i < ary.length; i++) {
const cur = ary[i];
for (let j = 0; j < newAry.length; j++) {
if (cur < newAry[j]) {
newAry.splice(j, 0, cur);
break;
}
if (j == newAry.length - 1) {
newAry.push(cur);
break;
}
}
}
return newAry;
}

数组求最大值

const max = ary.reduce((pre, item) => {
return pre > item ? pre : item;
}, 0);
console.log(max);
const max1 = Math.max(...ary);

类数组转数组

function listToArray(likeArray) {
var ary = [];
try {
ary = Array.prototype.slice.call(likeArray)
} catch (e) {
for (var i = 0; i < likeArray.length; i++) {
ary[ary.length] = likeArray[i]
}
}
return ary;
}

Array.prototype.slice.call(arrayLick)

Array.prototype.slice.apply(arrayLick)

Array.from(arrayLick)