Array.from使用技巧

es6中数组扩展了新的方法;Array.form,我们看看有什么好玩的用处。

# Array.form 介绍

Array.from() 方法从一个类数组或可迭代对象创建一个新的,浅拷贝的数组实例。

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

第一个参数必传,为类数组;第二个参数可选,是一个map函数,将逐一数组元素进行处理并返回。

# arrayLike-类数组

JavaScript 类数组对象的定义:

  1. 可以通过索引访问元素,并且拥有 length 属性;
  2. 没有数组的其他方法,例如 push , forEach , indexOf 等。

举例说明:字符串 abc,对象 {'1':1212,'2':1212,length:6} 都是类数组。

《javascript权威指南》上给出了代码用来判断一个对象是否属于“类数组”。

// Determine if o is an array-like object.
// Strings and functions have numeric length properties, but are 
// excluded by the typeof test. In client-side JavaScript, DOM text
// nodes have a numeric length property, and may need to be excluded 
// with an additional o.nodeType != 3 test.
function isArrayLike(o) {
    if (o &&                                // o is not null, undefined, etc.
        typeof o === 'object' &&            // o is an object
        isFinite(o.length) &&               // o.length is a finite number
        o.length >= 0 &&                    // o.length is non-negative
        o.length===Math.floor(o.length) &&  // o.length is an integer
        o.length < 4294967296)              // o.length < 2^32
        return true;                        // Then o is array-like
    else
        return false;                       // Otherwise it is not
}

lodash库也有相关判断方法 (opens new window)

_.isArrayLike([1, 2, 3]);
// => true
 
_.isArrayLike(document.body.children);
// => true
 
_.isArrayLike('abc');
// => true
 
_.isArrayLike(_.noop);
// => false

# 第二个参数

Array.from() 方法有一个可选参数 mapFn,让你可以在最后生成的数组上再执行一次 map 方法后再返回。利用这个参数我们可以做一些技巧性操作。

# 技巧运用

# nodeList转数组

ArrayLike对象指具有数组某些行为的对象,具体表现就是具有length属性。 有两种最常见的有两种:DOM中的NodeList和函数中的arguments。

通常使用for循环或者[...nodeList] 运算就就可以转换。

当然也可以这样

const args = [].slice.call(arguments);
const imgs = [].slice.call(document.querySelectorAll('img'));

现在又多了一种方法,可以这样

const args = Array.from(arguments);
const imgs = Array.from(document.querySelectorAll('img'));

arguments 同理

function fun() {
  return Array.from(arguments);
}

fun(1, 2, 3);

// [ 1, 2, 3 ]

# 字符串转数组

同样的字符串也多了一种数组转换的方式

function fun(str) {
  return Array.from(str);
}

fun('abcd');

// [ a, b, c ,d ]

# Map和Set转数组

从set生成数组,用此方法可以数组去重复。

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

从map生成数组

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'];

# 填充对象

Array.from({length:20},()=>{return {}});

# 填充随机数数组

Array.from({ length: 5 }, Math.random)
// [0.3160631607676865, 0.5155864876234266, 0.3654605814267633, 0.7502778910019559, 0.2978960060832099]
Array.from({ length: 5 }, Math.random).map(x=>parseInt(10*x))
// [8, 5, 7, 1, 2]

# 填充序列数组

Array.from({length:20},(v,i)=>i); // 可以这样

Array.from(Array(20).keys()); // 可以这样

[...Array(20).keys()] // 还可以这样,貌似更简洁

// 三种效果一致
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

# 填充指定范围序列数组

稍加改造,可以生成指定范围的序列数组

const range = (start, stop, step=1) => Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step));

range(56,100,3)
// [56, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 92, 95, 98]

// 生成奇数
range(1, 10, 2);
// [1, 3, 5, 7, 9]

// 字母序列
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"]

# 兼容性

下面是caniuse的兼容性列表,兼容性还是不错的。

# polyfill

由于es6是新特性旧项目万一有兼容性问题,可以添加polyfill (opens new window)替代方法

最近更新
01
echarts扇形模拟镜头焦距与可视化角度示意图
03-10
02
vite插件钩子
03-02
03
vite的依赖预构建
02-13
更多文章>