forEach究竟能不能改变原数组?
为什么使用forEach改变了数组中的某个值之后,数组却还是原模原样?让我们一起来试一试吧。
首先,准备一个简单的数字数组,改变了num的值之后,数组没有变化。
//数组-基本数据类型
let array = [1,2,3,4];
array.forEach(num => {
if(num === 4){
num = 5
}
})
console.log(array) //[1,2,3,4]
array.forEach(num => {
if(num === 4){
console.log(num === array[3]) //true
}
})
num和array[3]是全等的,但是数组又没有改变,怎么解释呢?实际上,因为它们都是基本数据类型,因此只要值一样,就是全等的。
let a = 1;
let b = 1;
console.log(a === b) //true
接着试一下复杂一点的引用类型数组:
//数组-基本数据类型
let array = [
{
name: '小红',
age: 12
},
{
name: '小明',
age: 18
},
];
array.forEach(person => {
if(person.name === '小红'){
person.age = 15
console.log(person === array[0]) //true
}
})
console.log(array) //[{name: '小红',age: 15},{name: '小明',age: 18},]
可以看到,小红的年龄确实改变了,这是不是说明引用数据类型就可以被自由的改变呢?下面尝试一下改变整个person:
array.forEach(person => {
if(person.name === '小红'){
person = {
name: '小红',
age: 15
},
console.log(person === array[0]) //false
}
})
console.log(array) //[{name: '小红',age: 12},{name: '小明',age: 18},]
可以发现用这种方式改变数组是不行的。
结论:forEach不能改变数组本身,无论是基础数据类型还是引用数据类型都不可以。
但是!可以用改变person.age的方式改变数组,原理在这儿:
person是一个对象,它里面存的其实是一个
指针
,这个指针存在栈内存(相当于浅层的存储区,用来存一些基本的简单数据)里面,这个指针指向的是堆内存里面的实际数据,也就是说,你拿到的person不是{name: ‘小红’,age: 15}这串数据本身,而是指向这串数据的地址,forEach里面不允许改变person的值,也就是说这个地址是改变不了的,就比如里面存的是‘湖滨小区1幢204’,这个地址被保护起来了,person也就只能指向这间房间,但是如果不改变房间,把房间里住的人变了可以吗?当然可以,这个forEach就管不着了,所以改变person.age就相当于把房间里的人给换了,相当于偷梁换柱,是可以实现的,这样就改变了array。
所以,最好不要尝试用forEach来改变数组的值,用for循环都比它好使。要在forEach里面改变数组,需要用array[index]的方法来改变数组本身。这样就需要在forEach里面穿第二个参数index。
array.forEach((person, index) => {
if(person.name === '小红'){
array[index].age = 15
}
})
console.log(array) //[{name: '小红',age: 15},{name: '小明',age: 18},]