day09 - JavaScript有关数组和对象的的深拷贝和浅拷贝问题
Posted 小高今天早睡了吗?
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了day09 - JavaScript有关数组和对象的的深拷贝和浅拷贝问题相关的知识,希望对你有一定的参考价值。
一、 数据类型
我们知道数据类型分为两类:
基本数据类型:string、number、boolean、null、undefined
存储方式:存储在栈内存中,变量存储的就是值
引用数据类型:Object(在JS中除了基本数据类型以外的都是对象,数据是对象,函数是对象,正则表达式是对象)
存储方式:存储在堆内存中,变量存储的是地址
具体通过代码来分析:
//基本数据类型:number 变量存储值,
//所以此时 b = a 赋值是把 a 的值复制一份给b
var a = 2 ;
var b = a ;
b++ ;
console.log(a) ; // 2
//引用数据类型:变量存储地址
//因为arr与arr2共用一个地址,改变arr2也会改变arr
var arr = [1,2,3] ;
var arr2 = arr ;
arr2.push(4) ;
console.log(arr) ; //[1,2,3,4]
可以通过以下图片分析。arr2 = arr 说明这两个引用数据类型指向了同一个堆内存对象。arr赋值给 arr2,实际上他们共同指向了同一个堆内存对象,所以修改 arr2 其实就是修改那个对象,所以通过 arr 也可以访问到,arr也发生了改变
二、数组的深拷贝和浅拷贝
1.数组的浅拷贝:只复制了地址(共享地址)
// 数组的浅拷贝 --- 只是复制了地址
var arr = [1,2,3,4,5] ;
var arr2 = arr ; //此时arr与arr2公用一个地址
2.数组的深拷贝:复制值
遍历(把原数组中的值存入新的数组) var arr2 = [] ;
slice() 截取数组中的所有值,得到的是一个新数组
方法一:通过遍历复制数组中的值(深拷贝)
// 数组的深拷贝 --- 复制数组中的值
var arr = [1,2,3,4,5] ;
var arr3 = [] ;
//通过遍历复制数组中的值
arr.forEach(function (v)
//将arr中的值添加到arr3中
arr3.push(v) ;
)
arr3.push('heolle') ;
console.log(arr) ; //[1, 2, 3, 4, 5]
console.log(arr3) ; //[1, 2, 3, 4, 5, 'heolle']
方法二:通过slice()截取数组中的值(深拷贝)
// 数组的深拷贝 --- 复制数组中的值
var arr = [1,2,3,4,5] ;
var arr3 = arr.slice() ;
//或写成 var arr3 = arr.slice(0 , arr.length)
arr3.push('hello') ;
console.log(arr3) ; //[1, 2, 3, 4, 5, 'hello']
console.log(arr) ; //[1, 2, 3, 4, 5]
三、函数的值传递与引用传递
函数传参时:
1.基本数据类型传递的是值
var a = 1 ;
function fn(n)
n++ ;
fn(a) ; //基本数据类型只是传递了值过去
console.log(a) ; // 1
2.引用数据类型传递的是地址(形参和实参共享地址),因此在封装函数的时候:如果改变原数组,就直接操作形参; 如果不想改变原数组,就实现深拷贝,然后操作新的数
var arr = [1,2,3] ;
function fn2(arr2)
arr2.push('a') ;
fn2(arr) ; //引用数据类型传递的是地址
console.log(arr) ; //[1,2,3,'a']
例子分析:
思路:假设每个存储的地址就是一个房间
function pop(arr)
// arr = arr3 ; // arr和arr3存储在608房间
var newArr = [] ; // newArr存储在609房间
for(var i = 0 ; i < arr.length - 1 ; i++)
newArr.push(arr[i])
// arr = newArr ; // arr newArr存储在 609
return newArr
var arr3 = [6,7,4,2,9,1] ; // 608
var res = pop(arr3) ;
console.log(res); //
console.log(arr3);
arr3 = res ;
var arr = [1,2,3] ; // 存储在608房间
arr = [6,7,9] ; // 存储在609房间
四、二维数组
1.二维数组的表示 arr[ i ][ j ] , i 表示第几行、j 表示第几列
//定义一个二维数组
var arr = [
[1, 2, 3],
[4, 5, 6],
[2, 3, 4]
]
console.log(arr) ;
console.log(arr[0][1]) ; //表示第一行第二个
2.二维数组遍历
for(var i in arr)
for(var j in arr[i])
console.log(arr[i][j]);
利用二维数组封装concat() 实现数组的拼接
//利用二维数组封装concat() 实现数组的拼接
function concat()
//打印出数组中的值
console.log(arguments) ;
var newArr = [] ;
//遍历数组
for(var i in arguments)
for(var j in arguments[i])
console.log(arguments[i][j]) ;
newArr.push(arguments[i][j]) ;
console.log(newArr);
concat([1,2,3] , [4,5,6]) ;
3.多维数组的深拷贝
1.多维数组深拷贝如果我们采用一般的slice截取,这种方法只是复制了数组的第一维,由于数组第一维存放的是第二维的引用,而第二维才是实际存放了他们的内容。这时候我们需要用for循环一个个拷贝一维数组
function deepArr(arr)
//定义一个新数组,存储传过来的值
var newArr = [] ;
//循环遍历数组的值,此时遍历的是第一维
for(var i = 0 ; i < arr.length ; i++)
//判断,如果遇到二维,就回调遍历第二维的值,然后放入newAree
if(Array.isArray(arr[i]))
//继续遍历,还是得到一个数组
var list = deepArr(arr[i]) ;
//再把得到的数组放入 newArr
newArr.push(list) ;
else
newArr.push(arr[i]) ;
return newArr ;
var arr = [1,2,3,4,[5,6],7]
var res = deepArr(arr) ;
arr[4].push('hello') ;
console.log(arr) ; //[1, 2, 3, 4, [5,6,'hello'], 7]
console.log(res) ; //[1, 2, 3, 4, [5,6], 7]
///可以观察到当原数组arr发生了改变时,
//但是newArr没有发生改变,实现了二维数组的深拷贝,
//多维数组深拷贝原理也是一样的
五、对象
数组:存储同一种类型的数据,具有有序性
对象:描述同一类型的事物(属性,方法),具有无序性
对象拥有属性和方法,在javascript中,几乎所有的事物都是对象
属性:属性值
方法:函数
对象的两种访问方式 :
1.person[‘name’] person[‘age’]
2.点语法 person.name person.age
举个简单的例子吧~
//定义一个对象
var person =
//属性值
name : '师爷',
age : 42 ,
sex : '男',
hobby : 'girl' ,
//方法
say : function ()
console.log('hello world');
,
nickname : ''
console.log(person.name); // 师爷
console.log(person['age']) ; // 42
对象的遍历:
var dog =
name : '二哈',
age : 3 ,
sex : '公',
say : function ()
console.log('汪');
//遍历对象
for(var key in dog)
console.log(dog[key]) ;
实例化对象 与 对象的赋值
// 实例化对象 -- 空对象
var obj = new Object() ;
// 赋值
obj.name = '奔驰' ;
obj.color = 'pink' ;
obj.price = '100w' ;
对象的深拷贝和浅拷贝:
浅拷贝:拷贝的是地址
var person1 =
name : '方总' ,
age : 18
//浅拷贝
var person2 = person1 ;
person2.name = '师爷' ;
console.log(person1) ; //此时person1的name属性也是'师爷'
深拷贝:拷贝的是值
//深拷贝 , 通过遍历赋值
var person2 = new Object() ;
for(var key in person1)
//将person1的值通过遍历赋给person2
person2[key] = person1[key] ;
console.log(pesson2) ;
person2.age = 20 ;
console.log(person1) ;
//此时person2的age属性变成了20,但是person1的属性还是18
以上是关于day09 - JavaScript有关数组和对象的的深拷贝和浅拷贝问题的主要内容,如果未能解决你的问题,请参考以下文章