ES6的Array.from()与Array.of()用法

只谈情不闲聊 提交于 2021-02-18 17:52:09

参考文献:《ES6 标准入门》

    ES6中最让人享福的地方之一就是它的新增数组应用的方法,同时,数组是JavaScript中最常见的数据集合,而ES6中新增的数组应用的方法能够提高我们的工作效率和简化我们的代码.所以今天小D就为大家一起来学习ES6中的Array.from()Array.of().

Array.from()

    Array.from()方法用于将两类对象转为真正的数组

  • 类似数组的对象(array-like object)

  • 可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)

这里我们解释一下什么叫做类似数组对象,如下代码所示:

let student = {
    0:'ElegantCode',
    1:'18',
    2:'boy',
    length3
}

我们可以在上面的对象student中发现,类似数组对象有两个特点:

      1. 它必须是一个对象
       2. 它有 length 属性

一个对象的所有键名都是正整数或零,并且有length属性,那么这个对象就很像数组,语法上称为“类似数组的对象”(array-like object)。“类似数组的对象”的根本特征,就是具有length属性。只要有length属性,就可以认为这个对象类似于数组。但是有一个问题,这种length属性不是动态值,不会随着成员的变化而变化

let student = {
    0:'ElegantCode',
    1:'18',
    2:'boy',
    length3
}
let arr = [1,2,3]
student.push(arr)
console.log(arr) 
// Uncaught TypeError: student.push is not a function

那么,也正因为类似数组的对象不是数组,所以它本身不具备数组的方法,浏览器报错。我们这时候就可以使用Array.from()方法将它转为真正的数组:

let student = {
    0:'ElegantCode',
    1:'18',
    2:'boy',
    length3
}
//ES5
var arr1 = [].slice.call(student); 
console.log(arr1) //["ElegantCode", "18", "boy"]
// //ES6
let arr2 = Array.from(student);
console.log(arr2) //["ElegantCode", "18", "boy"]

实际应用中,常见的类似数组的对象是 DOM 操作返回的 NodeList 集合,以及函数内部的arguments对象Array.from都可以将它们转为真正的数组。

什么是 NodeList 集合?

NodeList实例对象是一个类似数组的对象,它的成员是节点对象Node.childNodes、document.querySelectorAll()返回的都是NodeList实例对象。

//html代码
//<div class="dom"></div>
var all = document.querySelectorAll('.dom')
console.log(all) //NodeList [div.dom]

什么是arguments对象?

 arguments是一个对应于传递给函数的参数的类数组对象,比如:

function func1(a, b, c{
    console.log(arguments[0]);
    // 1
    console.log(arguments[1]);
    // 2
    console.log(arguments[2]);
    // 3
}
func1(123);

假如用Array.from都可以将它们转为真正的数组,那么代码将如下所示:

// NodeList对象
let a = Array.from(all).filter(dom => {
    return dom.textContent.length >100;
});
console.log(a) //[]

// arguments对象
function func1(a, b, c{
    var args = Array.from(arguments);
    console.log(args)
    //[1, 2, 3]
}
func1(123);

另外,只要是部署了 Iterator 接口的数据结构,Array.from都能将其转为数组:

Array.from('ElegantCode')
// ['E','l','e','g','a','n','t','C','o','d','e']

let namesSet = new Set(['a''b'])
Array.from(namesSet) 
// ['a', 'b']

上面代码中,字符串和 Set 结构都具有 Iterator 接口,因此可以被Array.from转为真正的数组。

Array.from([123])
// [1, 2, 3]

注:如果参数是一个真正的数组,Array.from会返回一个一模一样的新数组。

当然,值得一讲的还是扩展运算符(...)也可以将某些数据结构转为数组,扩展运算符背后调用的是遍历器接口(Symbol.iterator),如果一个对象没有部署这个接口,就无法转换。Array.from方法还支持类似数组的对象。所谓类似数组的对象,本质特征只有一点,即必须有length属性。因此,任何有length属性的对象,都可以通过Array.from方法转为数组,而此时扩展运算符就无法转换

Array.from({ length3 });
// [ undefined, undefined, undefined ]

上面代码中,Array.from返回了一个具有三个成员的数组,每个位置的值都undefined。扩展运算符转换不了这个对象。

Array.from还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组

Array.from(arrayLike, x => x * x);
// 等同于
Array.from(arrayLike).map(x => x * x);

Array.from([123], (x) => x * x)
// [1, 4, 9] ( 1*1 2*2 3*3 )

如果map函数里面用到了this关键字,还可以传入Array.from的第三个参数,用来绑定this

Array.from()可以将各种值转为真正的数组,并且还提供map功能。这实际上意味着,只要有一个原始的数据结构,你就可以先对它的值进行处理,然后转成规范的数组结构,进而就可以使用数量众多的数组方法

Array.from({ length2 }, () => 'ElegantCode')
// ['ElegantCode', 'ElegantCode']

上面代码中,Array.from的第一个参数指定了第二个参数运行的次数。这种特性可以让该方法的用法变得非常灵活。

Array.from()的另一个应用是,将字符串转为数组,然后返回字符串的长度。

function countSymbols(string{
  return Array.from(string).length;
}

因为它能正确处理各种 Unicode 字符,可以避免 JavaScript 将大于\uFFFF的 Unicode 字符,算作两个字符的 bug

Array.of()

Array.of方法用于将一组值,转换为数组

let arr = [123]
let i = Array.of(...arr)
console.log(i) // [1,2,3]
console.log( Array.of(i.length)) // [3]

为什么ES6中要新增这个方法呢?这个方法的主要目的,是弥补数组构造函数Array()的不足。因为参数个数的不同,会导致Array()的行为有差异

Array() // []
Array(3// [, , ,]
Array(3118// [3, 11, 8]

上面代码中,Array方法没有参数、一个参数、三个参数时,返回结果都不一样:

  • 只有当参数个数不少于 2 个时,Array()才会返回由参数组成的新数组

  • 参数个数只有一个时,实际上是指定数组的长度

Array.of基本上可以用来替代Array()new Array(),并且不存在由于参数不同而导致的重载。它的行为非常统一。

Array.of() // []
Array.of(undefined// [undefined]
Array.of(1// [1]
Array.of(12// [1, 2]

Array.of总是返回参数值组成的数组。如果没有参数,就返回一个空数组。

Array.of方法可以用下面的代码模拟实现。

function ArrayOf(a,b,c){
  return [].slice.call(arguments);
}
console.log(ArrayOf(1,2,3)) //[1.2.3]

 小编会在后面继续发布与ES6相关的知识,希望你能够在后期继续关注和支持我们的文章。

我是代码搬运工--D,欢迎各位大佬留言点评。

本章结束,敬请期待~

ElegantCode

长按识别二维码关注公众号

一位萌新WEB爱好者的学习分享,

希望同大家一起在学习的路上共勉!




上期回顾:CSS的动态wave-水波特效

知识回顾:ES6的扩展运算符

本文分享自微信公众号 - 进击的切图仔(gh_f4aeac3d02b4)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!