JS之splice()方法刨根问底

目录

语法

参数

返回值

技术细节

浏览器支持 

实例

源码


今天在使用JS处理字符串数组寻找好用的方法时,发现了一位全能选手splice(),为什么说它是全能选手呢?因为它可以删除元素,也可以添加元素,而且还可以同时进行删除和添加元素的操作,666啊,接下来让我们了解一下这位神奇的朋友。

先看基本语法:

语法

array.splice(index,howmany,item1,.....,itemX)

扫描二维码关注公众号,回复: 11321096 查看本文章

参数

参数 描述
index 必需。规定从何处添加/删除元素。
该参数是开始插入和(或)删除的数组元素的下标,必须是数字。
howmany 可选。规定应该删除多少元素。必须是数字,但可以是 "0"。
如果未规定此参数,则删除从 index 开始到原数组结尾的所有元素。
item1, ..., itemX 可选。要添加到数组的新元素

返回值

Type 描述
Array 如果从 arrayObject 中删除了元素,则返回的是含有被删除的元素的数组。

技术细节

JavaScript 版本: 1.2

浏览器支持 

基本上所有主要浏览器都支持splice()方法,比如IE、Firefox、欧朋、Chrome、Safari等。

实例

在本例中我们将删除位于 index=3 的元素,并添加一个新元素来替代被删除的元素:

var arr = new Array(6)
arr[0] = "Geo"
arr[1] = "John"
arr[2] = "Tome"
arr[3] = "James"
arr[4] = "Adrew"
arr[5] = "Marter"

document.write(arr + "<br />")
arr.splice(3,1,"William")
document.write(arr)

运行结果: 

Geo,John,Tome,James,Adrew,Marter
Geo,John,Tome,William,Adrew,Marter

源码

方法splice()在底层的源码实现中,实际上对应着方法ArraySplice(),源码位于v8/src/js/array.js中。二者的对应关系是在InstallFunctions中绑定的,具体看代码:

// Set up non-enumerable functions of the Array.prototype object and
// set their names.
// Manipulate the length of some of the functions to meet
// expectations set by ECMA-262 or Mozilla.
// 方法名对应的绑定关系列表
utils.InstallFunctions(GlobalArray.prototype, DONT_ENUM, [
  "toString", getFunction("toString", ArrayToString),
  "toLocaleString", getFunction("toLocaleString", ArrayToLocaleString),
  "join", getFunction("join", ArrayJoin),
  "pop", getFunction("pop", ArrayPop),
  "push", getFunction("push", ArrayPush, 1),
  "reverse", getFunction("reverse", ArrayReverse),
  "shift", getFunction("shift", ArrayShift),
  "unshift", getFunction("unshift", ArrayUnshift, 1),
  "slice", getFunction("slice", ArraySlice, 2),
  "splice", getFunction("splice", ArraySplice, 2),
  "sort", getFunction("sort", ArraySort),
  "filter", getFunction("filter", ArrayFilter, 1),
  "forEach", getFunction("forEach", ArrayForEach, 1),
  "some", getFunction("some", ArraySome, 1),
  "every", getFunction("every", ArrayEvery, 1),
  "map", getFunction("map", ArrayMap, 1),
  "indexOf", getFunction("indexOf", null, 1),
  "lastIndexOf", getFunction("lastIndexOf", ArrayLastIndexOf, 1),
  "reduce", getFunction("reduce", ArrayReduce, 1),
  "reduceRight", getFunction("reduceRight", ArrayReduceRight, 1),
  "copyWithin", getFunction("copyWithin", ArrayCopyWithin, 2),
  "find", getFunction("find", ArrayFind, 1),
  "findIndex", getFunction("findIndex", ArrayFindIndex, 1),
  "fill", getFunction("fill", ArrayFill, 1),
  "includes", getFunction("includes", null, 1)
]);

其中,ArraySplice()方法的具体实现如下:

function ArraySplice(start, delete_count) {
  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.splice");

  var num_arguments = arguments.length;
  var array = TO_OBJECT(this);
  var len = TO_LENGTH(array.length);
  var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len);
  var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len,
                                           start_i);
  var deleted_elements = ArraySpeciesCreate(array, del_count);
  deleted_elements.length = del_count;
  var num_elements_to_add = num_arguments > 2 ? num_arguments - 2 : 0;

  if (del_count != num_elements_to_add && %object_is_sealed(array)) {
    throw %make_type_error(kArrayFunctionsOnSealed);
  } else if (del_count > 0 && %object_is_frozen(array)) {
    throw %make_type_error(kArrayFunctionsOnFrozen);
  }

  var changed_elements = del_count;
  // 如果删除的元素个数和增加的元素个数不一致,则计算需要移动的元素位数
  if (num_elements_to_add != del_count) {
    // If the slice needs to do a actually move elements after the insertion
    // point, then include those in the estimate of changed elements.
    changed_elements += len - start_i - del_count;
  }
  if (UseSparseVariant(array, len, IS_ARRAY(array), changed_elements)) {
    %NormalizeElements(array);
    if (IS_ARRAY(deleted_elements)) %NormalizeElements(deleted_elements);
    SparseSlice(array, start_i, del_count, len, deleted_elements);
    SparseMove(array, start_i, del_count, len, num_elements_to_add);
  } else {
    SimpleSlice(array, start_i, del_count, len, deleted_elements);
    SimpleMove(array, start_i, del_count, len, num_elements_to_add);
  }

  // 从删除元素的位置开始添加元素 
  var i = start_i;
  var arguments_index = 2;
  var arguments_length = arguments.length;
  while (arguments_index < arguments_length) {
    array[i++] = arguments[arguments_index++];
  }
  array.length = len - del_count + num_elements_to_add;

  // 返回删除的元素
  return deleted_elements;
}

参考链接

http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.12

https://github.com/v8/v8/blob/ad82a40509c5b5b4680d4299c8f08d6c6d31af3c/src/js/array.js

https://www.w3school.com.cn/jsref/jsref_splice.asp

猜你喜欢

转载自blog.csdn.net/liuzehn/article/details/106769936
今日推荐