本文深入解析JavaScript数组的基础特性,涵盖数组的创建方式、类型检测的演进与缺陷、length属性的特殊行为以及遍历数组的最佳实践。通过对比Array构造函数与字面量、instanceof与Array.isArray的区别,以及for-in与for循环的性能差异,帮助开发者掌握更稳健的数组操作技巧。
JavaScript数组概述
JavaScript作为一门功能强大的语言,其数组类型也具备独特的行为。本文旨在梳理常用且最优的数组使用实践,剔除不推荐的用法。若文中存在疏漏,欢迎指正。
JavaScript中的数组本质上是一种特殊的对象,继承了对象的特性。当属性的键为连续且较小的整数时,应优先使用数组;否则,使用普通对象更为合适。
数组的来源与构造
数组的构造与创建
所有的数组实例均由Array构造函数生成。我们可以通过检查constructor属性来验证这一点。
var arr = [];
arr.constructor === Array; // true
arr.constructor === Array.prototype.constructor; // true
创建数组的几种方式
//数组字面量方式
var arr1 = [1, 2, 3]; // [1,2,3]
//构造函数方式
var arr2 = new Array(); // [] 空数组
var arr3 = new Array('9'); // ["9"] 一个字符串元素
var arr4 = new Array(9); // [] 数组长度length为9
var arr5 = new Array([9]); // [[9]] 相当于二维数组
var arr6 = new Array(1, 2, 3); // [1, 2, 3]
var arr7 = new Array(1, function f(){}, {o : 6}, null,undefined,true);
// 数组可以存储任意混合数据类型
因arr4的构造方式,当向Array构造函数仅传入一个数字参数时,该函数会返回一个设置了length属性的空数组。故建议使用数组字面量方式,其更为短小简洁。
数组类型检测方法
检测对象是否为数组
var arr1 = [1, 2, 3];
typeof(arr1); // object
众所周知,typeof运算符无法正确区分数组和普通对象,它总是返回object。
arr1 instanceof Array; //true
使用instanceof运算符在单一页面环境中通常有效,但在涉及跨窗口或嵌套iframe的场景下,由于存在多个全局作用域,该检测方法可能会失效。
Array.isArray(arr1); // true
Array.isArray()是ECMAScript 5标准引入的方法,它没有上述作用域问题,是目前推荐的检测方式。不过需注意,IE8及以下版本不支持该方法,且在IE9的严格模式下也存在兼容性问题。
Object.prototype.toString.apply(arr1).slice(8, -1); // Array
另一种可靠的检测方式是利用Object.prototype.toString.call()方法,通过截取返回字符串中的类型部分来判断,这通常被视为最稳健的检测手段。
length属性的行为
数组长度length属性解析
数组的length属性不仅表示元素个数,它本身也是数组的一个属性。即使增大length值,也不会触发越界错误。length的值等于数组中最大的整数属性名加1。
var arr1 = [];
arr1[9] = 1; // 长度为10,只包含一个元素的数组
如果将length设置为较小的值,所有整数属性名大于或等于新length值的元素将被自动删除。特别地,将length设为0等同于清空数组中的所有元素。
var arr2 = [1, 2, 3, 4, 5];
arr2.length = 3; // [1, 2, 3]
arr2.length = 0; // []
数组遍历的最佳实践
数组遍历的最佳实践
在遍历数组时,应避免使用for-in循环,因为它会遍历原型链上的所有可枚举属性,而不仅仅是数组元素。推荐使用标准的for循环进行遍历。
var arr1 = [1, 2, 3];
arr1.test = 9;
//for in 方式
for(var prop in arr1){
cosole.log(prop, arr1[prop]);
}
// 输出如下
// 0 1
// 1 2
// 2 3
// test 9
//for循环方式
for(var i = 0, len = arr1.length; i < len; i++){
console.log(arr1[i]);
}
//输出如下
// 1
// 2
// 3
使用for-in遍历时,可能会意外获取到附加在数组上的自定义属性(如test)。虽然可以使用hasOwnProperty()进行过滤,但这会显著降低性能。因此,推荐使用for循环,并在循环前缓存数组长度,以避免每次迭代都访问length属性带来的性能开销(尽管现代浏览器已对此进行优化)。
小结
本文简要介绍了JavaScript数组的基础知识,包括创建、检测、长度管理和遍历方式,希望能帮助读者建立对Array更全面且准确的理解。后续文章将深入探讨数组的各种内置方法。
尽管JavaScript中存在许多令人困惑的概念,但随着学习的深入,开发者会逐渐掌握其精髓并享受编程的乐趣。