Array.from()
前提补充
数组和对象的区别
-
创建方式不同:数组表示有序数据的集合,而对象表示无序数据的集合。
-
数组的数据没有”名称”(name),对象的数据有”名称”(name)。
-
调用方法不同
-
对象键值唯一,数组可以重复
-
对象没有长度,不能用for循环
对象没有length属性,要获取对象的length值,可以通过Object.keys()转为array,再.length获取
let person = {
'name': 'tom',
'age': '65',
'sex': '男',
'friends': ['jane', 'john', 'Mary'],
};
console.log(person.length); // undefined
console.log(Object.keys(person)); // ['name', 'age', 'sex', 'friends']
console.log(Object.keys(person).length); // 4
什么是类数组
JavaScript 常见的类数组:
arguments
arguments是一个类数组对象,它也可以通过索引来操作数据,在调用函数时,我们所传递的实参都会在arguments中保存。
可以通过arguments . length来获取实参的长度
function foo() {
console.log(arguments);
};
foo(1, 2, 3);
注意:箭头函数是没有arguments的
const foo = () => {
console.log(arguments);
};
foo(1, 2, 3);
可用如下代替:
const foo = (...res) => {
console.log(res);
};
foo(1, 2, 3);
获取Dom元素方法返回的结果
比如getElementsByTagName、getElementsByClassName
<body>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</body>
<script>
console.log(document.getElementsByTagName('div'));
console.log(document.getElementsByClassName('box'));
console.log(document.querySelectorAll('.box')); // 返回的是一个NodeList对象
</script>
节点列表NodeList不是一个数组!
节点列表看起来可能是一个数组,但其实不是。
你可以像数组一样,使用索引来获取元素。
节点列表无法使用数组的方法: valueOf(), pop(), push(), 或 join() 。
HTMLCollection 与 NodeList 的区别
HTMLCollection 是 HTML 元素的集合。
NodeList 是一个文档节点的集合。
NodeList 与 HTMLCollection 有很多类似的地方:
NodeList 与 HTMLCollection 都与数组对象有点类似,可以使用索引 (0, 1, 2, 3, 4, …) 来获取元素。
NodeList 与 HTMLCollection 都有 length 属性。
HTMLCollection 元素可以通过 name,id 或索引来获取。
NodeList 只能通过索引来获取。
只有 NodeList 对象有包含属性节点和文本节点。
类数组和数组的区别
类数组结构与数组十分相似,但是却没有数组那么丰富的内建方法,通常类数组可能还拥有一些别的属性。
- 类数组是一个对象
- 类数组这个对象必须包含length属性
- 类数组中key是以数字或者数字的字符串组成
const HTMLCollection = document.getElementsByClassName('box');
console.log(HTMLCollection); // HTMLCollection(3) [div.box, div.box, div.box]
console.log(typeof HTMLCollection); // object
console.log(Object.prototype.toString.call(HTMLCollection)); // [object HTMLCollection]
function foo() {
console.log(arguments); // Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
console.log(typeof arguments); // object
console.log(Object.prototype.toString.call(arguments)); // [object Arguments]
};
foo(1, 2, 3);
console.log(typeof []); // object
console.log(Object.prototype.toString.call([])); // [object Array]
Array.from()用法
Array.from()方法通过拥有length属性的对象(类数组)
或可迭代对象(可以获取对象中的元素,如Map和Set等)
,来创建一个新的、浅拷贝的数组实例。
Array.from(arrayLike,mapFn,thisArg)
arrayLike:必选,想要转换成数组的伪数组对象或可迭代对象
mapFn:可选,如果指定了该参数,新数组中的每个元素会执行该函数(相当于Array.from(arrayLike).map(mapFn,thisArg);)
thisArg:可选,执行回调函数mapFn时this对象
1. 浅克隆一个数组
let arr = ['tom','65','男',['jane','john','Mary']];
let cloneArr = Array.from(arr);
console.log(cloneArr); // ['tom','65','男',['jane','john','Mary']]
// 浅拷贝 此处拷贝的是引用类型数据,则拷贝的只是引用地址
console.log(arr[3] === cloneArr[3]); // true
console.log(arr === cloneArr); // false
2. 将伪数组转换成数组
function foo() {
// console.log(arguments); // Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
// console.log(Object.prototype.toString.call(arguments)); // [object Arguments]
let arr = Array.from(arguments);
console.log(arr); // (3) [1, 2, 3]
console.log(Object.prototype.toString.call(arr)); // [object Array]
};
foo(1, 2, 3);
3. 将Set/Map结构的数据转换为真数组
Set
Set类似于数组,是一个数据集合,可以存储任何类型的唯一值,无论是原始值或者是对象引用,区别在于:
-
成员的值都是唯一的(没有重复值,可用于数组去重)
-
无序,set没有下标(索引号),所以不能使用通过索引获取元素的方法
-
不可以用字面量的形式创建,只能用实例化形式创建
const arr = [1, 5, 95, 8, 48, 1, 8, 48];
const mySet = new Set(arr);
console.log(mySet); // {1, 5, 95, 8, 48}
console.log(mySet[1]); // undefined set集合是没有索引的,所以不能使用通过索引获取元素的方法
Array.from()将Set实例转换为真数组
const arr = [1, 5, 95, 8, 48, 1, 8, 48];
console.log(new Set(arr)); // {1, 5, 95, 8, 48}
const newArr = Array.from(new Set(arr));
console.log(newArr); // [1, 5, 95, 8, 48]
Array.from
还可以接受第二个参数,作用类似于数组的map
方法,用来对每个元素进行处理,将处理后的值放入返回的数组。如下:
const arr = [1, 5, 95, 8, 48, 1, 8, 48];
const mySet = new Set(arr);
console.log(mySet); // {1, 5, 95, 8, 48}
const newArr = Array.from(mySet, (item) => item * 2);
console.log(newArr); // [2, 10, 190, 16, 96]
Map
Map类似于对象,也是键值对的数据集合,区别在于:
对象的键只能是字符串,而map的key可以是任意类型的数据
let map = new Map();
map.set(111, 222);
map.set(true, []);
map.set(NaN, {});
map.set({ name: '张三' }, 1111);
map.set({}, undefined);
map.set([1, 2], true);
console.log(map);
Array.from()将Map实例转换为真数组
const mapArr = Array.from(map);
console.log(mapArr);
得到的是一个二维数组:
4. 将字符串转换为数组
let str = 'hi world!';
let arr = Array.from(str);
console.log(arr); // ['h', 'i', ' ', 'w', 'o', 'r', 'l', 'd', '!']
数组去重
const arr = [1, 5, 95, 8, 48, 1, 8, 48];
// 利用扩展运算符+Set,数组去重
const uniqueArr = [...new Set(arr)];
console.log(uniqueArr); // [1, 5, 95, 8, 48]
// 利用Array.from()+Set,数组去重
const uniqueArr2 = Array.from(new Set(arr));
console.log(uniqueArr2); // [1, 5, 95, 8, 48]
并集
var a = new Set([1, 2, 3]);
var b = new Set([4, 3, 2]);
var union = new Set([...a, ...b]); // {1, 2, 3, 4}
交集
var a = new Set([1, 2, 3]);
var b = new Set([4, 3, 2]);
var intersect = new Set([...a].filter(x => b.has(x))); // {2, 3}
差集
var a = new Set([1, 2, 3]);
var b = new Set([4, 3, 2]);
var difference = new Set([...a].filter(x => !b.has(x))); // {1}