Array.prototype.concat()
描述
concat()
方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
concat
方法创建一个新的数组,它由被调用的对象中的元素组成,每个参数的顺序依次是该参数的元素(如果参数是数组)或参数本身(如果参数不是数组)。它不会递归到嵌套数组参数中。
concat
方法不会改变 this
或任何作为参数提供的数组,而是返回一个浅拷贝,它包含与原始数组相结合的相同元素的副本。原始数组的元素将复制到新数组中,如下所示:
- 对象引用(而不是实际对象):
concat
将对象引用复制到新数组中。原始数组和新数组都引用相同的对象。也就是说,如果引用的对象被修改,则更改对于新数组和原始数组都是可见的。这包括也是数组的数组参数的元素。 - 数据类型如字符串,数字和布尔:
concat
将字符串和数字的值复制到新数组中。
参数
valueN
可选
数组和/或值,将被合并到一个新的数组中。
如果不传参数则
concat
会返回调用此方法的现存数组的一个浅拷贝。
let list = [1, 2, 3];
let res = list.concat();
console.log(res);[1,2,3]
console.log(res === list);//false
返回值 新的 Array实例。
语法&示例
concat()
concat(value0)
concat(value0, value1)
concat(value0, value1, /* … ,*/ valueN)
const array1 = ['a', 'b', 'c'];
const array2 = ['d', 'e', 'f'];
const array3 = array1.concat(array2);
console.log(array3);
// expected output: Array ["a", "b", "c", "d", "e", "f"]
实现
Array.prototype._concat = function(){
//let arr = JSON.parse(JSON.stringify(this)); // 用JSON可以深度拷贝数组
let arr = [...this]
let args = [...arguments];
args.map(item=>{
if(Array.isArray(item)){
item.map(val=>{
arr.push(val)
})
}else{
arr.push(item)
}
});
return arr;
}
Array.prototype.slice()
描述
slice
不会修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。原数组的元素会按照下述规则拷贝:
- 如果该元素是个对象引用(不是实际的对象),
slice
会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变。 - 对于字符串、数字及布尔值来说,
slice
会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组。
如果向两个数组任一中添加了新元素,则另一个不会受到影响。
- 结果返回一个数组;
- 不传入参数则拷贝整个数组;
- 传入两个参数则拷贝
[start,end)
这个区间的元素(不包括end位置的元素); - 传入一个参数则拷贝该索引位置到数组末尾的所有元素;
- 参数为负数则该索引位置=参数+数组长度;
- 两个参数同为正、同为负的时候,
start < end
才能拷贝元素; - 拷贝最小从索引为0的位置开始,最长到拷贝整个数组
参数
begin
可选
提取起始处的索引(从 0
开始),从该索引开始提取原数组元素。如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取,slice(-2)
表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。如果省略 begin
,则 slice
从索引 0
开始。如果 begin
超出原数组的索引范围,则会返回空数组。
end
可选
提取终止处的索引(从 0
开始),在该索引处结束提取原数组元素。slice
会提取原数组中索引从 begin
到 end
的所有元素(包含 begin
,但不包含 end
)。slice(1,4)
会提取原数组中从第二个元素开始一直到第四个元素的所有元素(索引为 1, 2, 3 的元素)。如果该参数为负数,则它表示在原数组中的倒数第几个元素结束抽取。 slice(-2,-1)
表示抽取了原数组中的倒数第二个元素到最后一个元素(不包含最后一个元素,也就是只有倒数第二个元素)。如果 end
被省略,则 slice
会一直提取到原数组末尾。如果 end
大于数组的长度,slice
也会一直提取到原数组末尾。
语法&示例
slice()
slice(start)
slice(start, end)
let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(arr.slice()); // [0,1,2,3,4,5,6,7,8,9]
console.log(arr.slice(1)); // [1,2,3,4,5,6,7,8,9]
console.log(arr.slice(1, 4)); // [1,2,3]
console.log(arr.slice(1, 20)); // [1,2,3,4,5,6,7,8,9]
console.log(arr.slice(5, 1)); // []
console.log(arr.slice(-1)); // [9]
console.log(arr.slice(-1, -5)); // []
console.log(arr.slice(-1, -22)); // []
console.log(arr.slice(-22, -1)); // [0,1,2,3,4,5,6,7,8]
console.log(arr.slice(-22)); // [0,1,2,3,4,5,6,7,8,9]
console.log(arr.slice(-5, -1)); // [5,6,7,8]
console.log(arr.slice(1, -12)); // []
console.log(arr.slice(1, -2)); // [1,2,3,4,5,6,7]
实现
Array.prototype.slice = function (start, end) {
// 保存结果
let res = [];
// this指向调用slice方法的数组
let len = this.length;
// 参数默认值
// 没有传入start,从0开始截取
// 没有传入end,截取整个数组长度
start = start === undefined ? 0 : start;
end = end === undefined ? len : end;
// 边界处理
// start小于0,从star+len的位置截取
// 如果start+len依然小于0,从0开始截取
start = start < 0 ? start + len : start;
start = Math.max(0, start);
// end小于0,截取到end+len的位置
// 如果end+len继续小于0,由于start最小位置是0开始,这种情况循环截取条件不会成立
// 如果end大于数组元素长度len,截取整个数组长度
end = end < 0 ? end + len : end;
end = Math.min(end, len)
// 截取[start,end)这个区间的元素
// 隐含了start>end时循环条件不会成立的情况
for (let i = start; i < end; i++) {
res.push(this[i])
}
return res;
}