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有关数组和对象的的深拷贝和浅拷贝问题的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript之StringDateNumberMath数组对象day0912

year:2017 month:7 day:19

根据传递的输入过滤对象数组:Javascript

使用 JavaScript 在数组中查找最近的日期

什么是 jQuery 对象?

什么是 jQuery 对象?