各位靓仔靓女,晚上好!我是你们的老朋友,今天咱们来聊聊一个JavaScript里的小能手——Array.from()
。这玩意儿可别小看,它能把一些看着像数组,但其实不是数组的家伙,变成真正的数组,让你的代码更灵活,更方便。
开场白:真假美猴王?数组的身份危机
在JavaScript的世界里,数组是一种非常重要的数据结构。但是,有时候我们会遇到一些“伪数组”,它们长得像数组,用起来也像数组,但就是不折不扣的“假货”。比如,arguments
对象、NodeList
对象等等。这些家伙虽然有length
属性,也能通过索引访问元素,但它们没有数组的那些方法,比如push
、pop
、slice
等等。
这就很尴尬了,你想用数组的方法处理它们,却发现根本用不了。这时候,Array.from()
就闪亮登场了,它就像一个“验明正身”的工具,能把这些“伪数组”变成真正的数组,让你随心所欲地使用数组的方法。
Array.from()
的基本用法:变身大法
Array.from()
的基本语法如下:
Array.from(arrayLike, mapFn, thisArg)
arrayLike
:想要转换成数组的类数组对象或可迭代对象。mapFn
(可选):一个映射函数,用来对数组中的每个元素进行处理,生成新的数组。thisArg
(可选):执行mapFn
时this
的值。
最简单的用法就是直接把一个类数组对象转换成数组:
// 1. arguments对象
function foo() {
let args = Array.from(arguments);
console.log(args); // 输出: [1, 2, 3]
console.log(Array.isArray(args)); // 输出: true
}
foo(1, 2, 3);
// 2. NodeList对象
let listItems = document.querySelectorAll('li');
let listArray = Array.from(listItems);
console.log(listArray); // 输出: [li, li, li, ...]
console.log(Array.isArray(listArray)); // 输出: true
// 3. 字符串
let str = "hello";
let strArray = Array.from(str);
console.log(strArray); // 输出: ["h", "e", "l", "l", "o"]
console.log(Array.isArray(strArray)); // 输出: true
//4. Set
let mySet = new Set([1,2,3,3,4,5]);
let setArray = Array.from(mySet);
console.log(setArray); // 输出: [1, 2, 3, 4, 5]
//5. Map
let myMap = new Map([['a', 1], ['b', 2]]);
let mapArray = Array.from(myMap);
console.log(mapArray); // 输出: [['a', 1], ['b', 2]]
可以看到,Array.from()
就像一个魔法棒,轻轻一挥,就能把各种各样的类数组对象变成真正的数组。
mapFn
:锦上添花的映射功能
Array.from()
还有一个强大的功能,就是可以通过mapFn
参数对转换后的数组进行映射处理。这个mapFn
本质上就是一个函数,它接收数组中的每个元素作为参数,然后返回一个新的值,这个新的值就会被放到最终的数组中。
// 将NodeList转换为数组,并将每个li元素的textContent提取出来
let listItems = document.querySelectorAll('li');
let textArray = Array.from(listItems, item => item.textContent);
console.log(textArray); // 输出: ["Item 1", "Item 2", "Item 3", ...]
// 将字符串转换为数组,并将每个字符转换为大写
let str = "hello";
let upperCaseArray = Array.from(str, char => char.toUpperCase());
console.log(upperCaseArray); // 输出: ["H", "E", "L", "L", "O"]
//将数字字符串转换为数字数组
let numberStrings = ["1","2","3"];
let numberArray = Array.from(numberStrings, Number);
console.log(numberArray); // 输出: [1, 2, 3]
这个mapFn
非常灵活,你可以根据自己的需求,对数组中的元素进行各种各样的处理。
thisArg
:控制this
的指向
thisArg
参数用来指定mapFn
函数执行时this
的值。这个参数在某些情况下非常有用,比如当你的mapFn
函数需要访问一个对象的属性或方法时,就可以通过thisArg
来指定this
的值。
let obj = {
multiplier: 2,
multiply: function(x) {
return x * this.multiplier;
}
};
// 使用thisArg来指定this的值为obj
let numbers = [1, 2, 3];
let multipliedArray = Array.from(numbers, function(num) {
return this.multiply(num);
}, obj);
console.log(multipliedArray); // 输出: [2, 4, 6]
在这个例子中,我们通过thisArg
将mapFn
函数中的this
指向了obj
对象,这样我们就可以在mapFn
函数中调用obj
对象的multiply
方法了。
Array.from()
的常见应用场景:解决你的燃眉之急
Array.from()
在实际开发中有很多应用场景,下面列举一些常见的例子:
- 将
arguments
对象转换为数组:在函数内部,arguments
对象是一个类数组对象,如果你想使用数组的方法处理函数的参数,就可以使用Array.from(arguments)
将其转换为数组。
function sum() {
let args = Array.from(arguments);
return args.reduce((acc, val) => acc + val, 0);
}
console.log(sum(1, 2, 3, 4)); // 输出: 10
- 将
NodeList
对象转换为数组:document.querySelectorAll()
方法返回的是一个NodeList
对象,如果你想对页面中的元素进行批量处理,就可以使用Array.from(NodeList)
将其转换为数组。
let listItems = document.querySelectorAll('li');
let textArray = Array.from(listItems, item => item.textContent);
console.log(textArray); // 输出: ["Item 1", "Item 2", "Item 3", ...]
- 将字符串转换为字符数组:如果你想对字符串中的每个字符进行处理,就可以使用
Array.from(string)
将其转换为字符数组。
let str = "hello";
let charArray = Array.from(str);
console.log(charArray); // 输出: ["h", "e", "l", "l", "o"]
- 生成指定长度的数组:
Array.from()
还可以用来生成指定长度的数组,这在某些场景下非常有用。
// 生成一个长度为5的数组,每个元素的值都为0
let zeroArray = Array.from({ length: 5 }, () => 0);
console.log(zeroArray); // 输出: [0, 0, 0, 0, 0]
// 生成一个长度为10的数组,每个元素的值都为它的索引
let indexArray = Array.from({ length: 10 }, (_, i) => i);
console.log(indexArray); // 输出: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
- 转换Set和Map为数组
//Set
const mySet = new Set([1, 2, 3, 4, 5]);
const myArray = Array.from(mySet);
console.log(myArray); // 输出: [1, 2, 3, 4, 5]
//Map
const myMap = new Map([
['a', 1],
['b', 2],
['c', 3]
]);
const mapArray = Array.from(myMap);
console.log(mapArray); // 输出: [['a', 1], ['b', 2], ['c', 3]]
Array.from()
与[...arrayLike]
:殊途同归,各有千秋
在ES6中,还有一个叫做“扩展运算符”(spread operator)的语法,也可以用来将类数组对象转换为数组。它的用法如下:
let args = [...arguments]; // 将arguments对象转换为数组
let listArray = [...document.querySelectorAll('li')]; // 将NodeList对象转换为数组
let strArray = [...'hello']; // 将字符串转换为数组
那么,Array.from()
和扩展运算符有什么区别呢?
- 兼容性:扩展运算符是ES6的语法,在一些老版本的浏览器中可能不支持。而
Array.from()
是ES6的API,但可以通过polyfill来兼容老版本的浏览器。 - 灵活性:
Array.from()
可以接受mapFn
和thisArg
参数,可以对转换后的数组进行映射处理,而扩展运算符则没有这个功能。 - 可读性:在某些情况下,
Array.from()
的可读性可能更好一些,尤其是在需要进行映射处理的时候。
总的来说,Array.from()
和扩展运算符都可以用来将类数组对象转换为数组,你可以根据自己的需求选择使用哪一个。如果需要兼容老版本的浏览器,或者需要进行映射处理,那么Array.from()
可能更适合你。如果只是简单地将类数组对象转换为数组,而且不需要兼容老版本的浏览器,那么扩展运算符可能更简洁一些。
Array.from()
的性能考量:效率至上
虽然Array.from()
非常方便,但是在性能方面,它可能不如直接使用循环来处理类数组对象。这是因为Array.from()
内部需要创建一个新的数组,并将类数组对象中的元素复制到新的数组中,这个过程会消耗一定的性能。
因此,在性能要求非常高的场景下,你可以考虑使用循环来处理类数组对象,避免使用Array.from()
。
// 使用循环来处理arguments对象
function sum() {
let total = 0;
for (let i = 0; i < arguments.length; i++) {
total += arguments[i];
}
return total;
}
console.log(sum(1, 2, 3, 4)); // 输出: 10
// 使用循环来处理NodeList对象
let listItems = document.querySelectorAll('li');
let textArray = [];
for (let i = 0; i < listItems.length; i++) {
textArray.push(listItems[i].textContent);
}
console.log(textArray); // 输出: ["Item 1", "Item 2", "Item 3", ...]
总结:Array.from()
,你值得拥有
总而言之,Array.from()
是一个非常实用的API,它可以将类数组对象或可迭代对象转换为真正的数组,让你的代码更灵活,更方便。虽然在性能方面可能不如直接使用循环,但是在大多数情况下,Array.from()
的便利性足以弥补这一点。所以,下次当你遇到类数组对象时,不妨试试Array.from()
,相信它会给你带来惊喜。
表格总结:Array.from()
的特性
特性 | 描述 |
---|---|
功能 | 将类数组对象或可迭代对象转换为真正的数组。 |
语法 | Array.from(arrayLike, mapFn, thisArg) |
arrayLike |
想要转换成数组的类数组对象或可迭代对象。 |
mapFn |
可选参数,一个映射函数,用来对数组中的每个元素进行处理,生成新的数组。 |
thisArg |
可选参数,执行mapFn 时this 的值。 |
应用场景 | 将arguments 对象、NodeList 对象、字符串等转换为数组,生成指定长度的数组。 |
兼容性 | ES6 API,可以通过polyfill兼容老版本浏览器。 |
与扩展运算符的区别 | Array.from() 可以接受mapFn 和thisArg 参数,可以对转换后的数组进行映射处理,而扩展运算符则没有这个功能。Array.from() 兼容性更好,但是性能可能不如扩展运算符。 |
性能 | 在性能要求非常高的场景下,可以考虑使用循环来处理类数组对象,避免使用Array.from() 。 |
今天的讲座就到这里,希望对大家有所帮助。记住,编程的世界充满了乐趣,只要你肯学习,肯实践,就能成为一名优秀的程序员!下次再见!