文章目录
slice() 方法
数组截取办法: slice()
,用于截取数组中的一部分,返回一个新的数组对象,不影响原数组。arr.slice(begin, end)
,slice
会提取原数组中索引从 begin
到 end
的所有元素(包含 begin
,但不包含 end
)。 注意 ❗ ❗ ❗ slice()
方法是浅拷贝,具体在下文做解释。
slice()
,用于截取数组中的一部分,返回一个新的数组对象,不影响原数组。
注意 ❗ ❗ ❗ slice()
方法是浅拷贝,具体在下文做解释。
arr.slice(begin, end)
,slice
会提取原数组中索引从 begin
到 end
的所有元素(包含 begin
,但不包含 end
)。
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 不会修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。原数组的元素会按照下述规则拷贝:
- 如果该元素是个对象引用 (不是实际的对象),
slice
会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变。 - 对于字符串、数字及布尔值来说(不是 String、Number 或者 Boolean 对象),
slice
会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组。
如果向两个数组任一中添加了新元素,则另一个不会受到影响。
下面通过实例详细了解一下 slice()
方法的浅拷贝:
下面的代码描述了修改数组的几种情况:
let menuTreeList = [{
"id": "cfda8029dfb311e7b555201a068c6482",
"name": "系统管理",
"menuType": 0,
"children": [{
"id": "3873ccc2dfda11e7b555201a068c6483",
"name": "菜单管理",
"menuType": 2,
"children": [{
"id": "18bf8d5df09511e78a57201a068c6484",
"name": "新增",
"menuType": 1
},
{
"id": "18bf8d5df09511e78a57201a068c6485",
"name": "修改",
"menuType": 1
}
]
}]
},
{
"id": "cfda8029dfb311e7b555201a068c6486",
"name": "设备管理",
"menuType": 0,
"children": [{
"id": "18bf8d5df09511e78a57201a068c6487",
"name": "新增",
"menuType": 1
},
{
"id": "18bf8d5df09511e78a57201a068c6488",
"name": "修改",
"menuType": 1
}
]
}
]
let a = menuTreeList.slice(0, 1);
console.group("1.修改对象深层属性")
// console.log('a :>> ', a);
// 1.被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变:
// 修改原始值 menuTreeList[0] ,即修改对象的引用
menuTreeList[0].children = [];
// 验证:
// 原来的数组:
console.log('被修改过的原来的数组 menuTreeList :>> ', menuTreeList);
// slice方法产生的新数组:
console.log('新的数组 a :>> ', a);
console.groupEnd()
let newArr = [1, 2, 3, 4, 5, 6];
let b = newArr.slice(0, 4);
console.group("2.验证数组元素为字符串、数字及布尔值时的情况")
// console.log('b :>> ', b);
// 2.对于字符串、数字及布尔值来说,slice 会拷贝这些值到新的数组里。
// 在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组:
newArr[0] = 0;
newArr[1] = 0;
newArr[2] = 0;
newArr[3] = 0;
// 原来的数组:
console.log('被修改过的原来的数组 newArr :>> ', newArr);
// slice方法产生的新数组:
console.log('新的数组 b :>> ', b);
console.groupEnd();
let newArr3 = [{
"id": "1",
"name": "设备管理",
"menuType": 0,
}, {
"id": "2",
"name": "设备管理",
"menuType": 0,
}, {
"id": "3",
"name": "设备管理",
"menuType": 0,
}, {
"id": "4",
"name": "设备管理",
"menuType": 0,
}];
let d = newArr3.slice(0, 3);
console.group("3.修改简单对象的属性 验证")
// console.log('d :>> ', d);
newArr3[0].id = "111111111";
newArr3[1].id = "111111111";
newArr3[2].id = "111111111";
// 原来的数组:
console.log('被修改过的原来的数组 newArr3 :>> ', newArr3);
// slice方法产生的新数组:
console.log('新的数组 d :>> ', d);
console.groupEnd();
let newArr2 = [{
"id": "1",
"name": "设备管理",
"menuType": 0,
}, {
"id": "2",
"name": "设备管理",
"menuType": 0,
}, {
"id": "3",
"name": "设备管理",
"menuType": 0,
}, {
"id": "4",
"name": "设备管理",
"menuType": 0,
}];
let c = newArr2.slice(0, 3);
console.group("4.把数组简单对象置空 验证")
// console.log('c :>> ', c);
newArr2[0] = {};
newArr2[1] = {};
newArr2[2] = {};
// 原来的数组:
console.log('被修改过的原来的数组 newArr2 :>> ', newArr2);
// slice方法产生的新数组:
console.log('新的数组 c :>> ', c);
console.groupEnd()
let newArr4 = [{
"id": "1",
"name": "设备管理",
"menuType": 0,
}, {
"id": "2",
"name": "设备管理",
"menuType": 0,
}, {
"id": "3",
"name": "设备管理",
"menuType": 0,
}, {
"id": "4",
"name": "设备管理",
"menuType": 0,
}];
let e = newArr4.slice(0, 3);
console.group("5.把数组简单对象元素改为基本数据类型 验证")
newArr4[0] = 0;
newArr4[1] = 0;
newArr4[2] = 0;
// 原来的数组:
console.log('被修改过的原来的数组 newArr4 :>> ', newArr4);
// slice方法产生的新数组:
console.log('新的数组 e :>> ', e);
console.groupEnd()
输出结果:
为什么把数组简单对象元素改为基本数据类型
和把数组简单对象置空
这两种情况下的数组都没有跟着改变呢?
这个问题我是向 CSDN博客专家「零一」学习的,字节跳动大佬,很多高质量原创文章,快来观摩