JavaScript数组核心方法深度解析与源码实现原理

作者:纸飞机

时间:2026-10-28

浏览:106

本文深入探讨JavaScript中数组的创建方式及核心方法。通过分析V8引擎源码,解析slice方法将类数组转换为真数组的内部机制,并对比splice与push的应用场景。同时详解sort排序器的数值处理及length属性的截断与扩容特性,帮助开发者理解底层实现并优化代码。

文章目录

JavaScript数组基础与创建方式

在JavaScript中,数组可以通过Array构造函数实例化,但更推荐使用方括号[]进行快速创建,这也是业界首选方案。尽管数组是Object原型的继承者,且typeof运算符对其返回'object',但这并不影响其作为有序集合的功能特性。

slice方法原理与类数组转换

1. Array.prototype.slice方法 slice方法不仅用于从现有数组中提取子集,还具备将“类数组对象”(如arguments对象或HTMLCollection集合)转换为标准数组的能力。

代码如下:

 
var nodesArr = Array.prototype.slice.call(document.forms);
var argsArr = Array.prototype.slice.call(arguments);

为何slice方法能实现这种转换?其在JavaScript引擎内部的实现机制是什么?其他类似方法是否具备相同能力?

为了解开疑惑,可以获取Google V8 JavaScript引擎的源代码进行本地研究,源码下载地址为:https://github.com/v8/v8。

在v8-master/src/array.js文件中搜索“Array.prototype.slice”:

代码如下:

function ArraySlice(start, end) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.slice");
  ...
var result = []; // 这句是关键
if (end_i < start_i) return result;
if (UseSparseVariant(array, len, IS_ARRAY(array), end_i - start_i)) {
     ...
SparseSlice(array, start_i, end_i - start_i, len, result);
} else {
SimpleSlice(array, start_i, end_i - start_i, len, result);
  }
  ...
return result;

推测调用类数组时执行的是SimpleSlice方法。在源码中搜索“SimpleSlice”,发现Array.prototype.splice方法也调用了该函数,且结果变量同样初始化为空数组。然而,若想利用splice将类数组转为真数组,必须传入起始位置参数0,即:

代码如下:

var nodesArr = Array.prototype.splice.call(document.forms, 0);

这是因为splice的实现逻辑是将被删除的项组成新数组返回。有兴趣的开发者可以查阅Array.prototype.splice的源码实现。 此外,slice方法还可用于克隆数组:

代码如下:

var arr = [1, 2, 3];
var cloneArr = arr.slice(); // cloneArr: [1, 2, 3]

push方法合并数组技巧

2. Array.prototype.push 方法 利用push方法可以实现数组合并:

代码如下:

var arr1 = [1, 'str', {name: 'lang'}];
var arr2 = [2, 'ing'];
Array.prototype.push.apply(arr1, arr2);
// 返回结果:[1, "str", {name: 'lang'}, 2, "ing"]

sort排序器与数值排序实现

3. Array.prototype.sort 方法 先看以下代码示例:

代码如下:

var arr = ['1', '2', '10', '12'];
arr.sort();
// 返回结果:["1", "10", "12", "2"]

上述结果通常不符合数值排序的预期。若需按数值大小排序,应如何处理:

代码如下:

arr.sort(function(a, b) {
return a - b;
})
// 返回结果:["1", "2", "10", "12"]

借助排序比较器函数,可以定义各种自定义比较逻辑,从而实现个性化的排序需求。

length属性的截断与扩容机制

4. length 属性 数组的length属性并非只读,它支持写入操作。例如,可以通过设置length属性来截断数组:

代码如下:

var arr = [1, 2, 3, 4];
arr.length = 2;
// arr: [1, 2]
arr.length = 0;
// arr: []

反之,若增大length属性值,数组长度会增加,新增的元素位置将被undefined填充。

代码如下:

var arr = [];
arr.length = 3;
// arr: [undefined, undefined, undefined]

至此总结完毕。鉴于时间已晚,未来若有新发现将在此补充。 此前缺乏写博客的习惯,仅习惯将在有道云笔记中记录日常总结,未曾想到将观点整理成文需要精心构思表达方式,以便读者更好地理解。

若文中存在表达不当或理解偏差之处,恳请读者指正。

另附一些常用的javascript数组方法

concat()连接两个或更多的数组,并返回结果。 join()把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。 pop()删除并返回数组的最后一个元素 push()向数组的末尾添加一个或更多元素,并返回新的长度。 reverse()颠倒数组中元素的顺序。 shift()删除并返回数组的第一个元素 slice()从某个已有的数组返回选定的元素 sort()对数组的元素进行排序 splice()删除元素,并向数组添加新元素。 toSource()返回该对象的源代码 toString()把数组转换为字符串,并返回结果。 toLocaleString()把数组转换为本地数组,并返回结果。 unshift()向数组的开头添加一个或更多元素,并返回新的长度。 valueOf()返回数组对象的原始值

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章