美文网首页
数组、对象的各种处理

数组、对象的各种处理

作者: 5df463a52098 | 来源:发表于2018-10-26 13:45 被阅读8次

一、数组

1、复制

   var arr1 = [1, 2, 3]
    var arr2 = arr1
    console.log(arr1) // [1, 2, 3]
    console.log(arr2) // [1, 2, 3]
    arr2[0] = 5
    console.log(arr1) // [5, 2, 3]
    console.log(arr2) // [5, 2, 3]

浅copy,两个数组指向同一个地址,一个改变了数组的值,另一个也随之改变。这样的copy并非我们需要的,我们需要的是深copy,两个数组值一样,但是指向不同的地址,一个数组的改变不会影响另一个数组。

方法一:for遍历
var arr1 = [1, 2, 3]
    var arr2 = []
    for (var i = 0; i < arr1.length; i++) {
        arr2.push(arr1[i])
    }
    console.log(arr1) // [1,2,3]
    console.log(arr2) // [1,2,3]
    arr2[0] = 5
    console.log(arr1) // [1,2,3]
    console.log(arr2) // [5,2,3]
方法二:slice方法(第一层copy)
var arr1 = [1, 2, 3]
    var arr2 = arr1.slice(0)
    console.log(arr1) // [1,2,3]
    console.log(arr2) // [1,2,3]
    arr2[0] = 5
    console.log(arr1) // [1,2,3]
    console.log(arr2) // [5,2,3]
var arr3 = [1, 2, [3,4], {a: 5}]
    var arr4 = arr3.concat()
    arr4[2].push(6)
    arr4[3].a = 7
    console.log(arr3) // [1,2,[3,4,6], {a: 7}]
    console.log(arr4) // [1,2,[3,4,6], {a: 7}]

arr3 中含有数组 [3,4] 和对象 {a:5},如果我们直接修改数组和对象,不会影响 arr3,但是我们修改数组 [3,4] 或对象 {a:5} 时,发现 arr3 也发生了变化。所以,slice 只是对数组的第一层进行深拷贝

方法三:concat 方法(第一层copy)
 var arr1 = [1, 2, 3]
    var arr2 = arr1.concat()
    console.log(arr1) // [1,2,3]
    console.log(arr2) // [1,2,3]
    arr2[0] = 5
    console.log(arr1) // [1,2,3]
    console.log(arr2) // [5,2,3]

 var arr3 = [1, 2, [3,4], {a: 5}]
    var arr4 = arr3.slice()
    arr4[2].push(6)
    arr4[3].a = 7
    console.log(arr3) // [1,2,[3,4,6], {a: 7}]
    console.log(arr4) // [1,2,[3,4,6], {a: 7}]

arr3 中含有数组 [3,4] 和对象 {a:5},如果我们直接修改数组和对象,不会影响 arr3,但是我们修改数组 [3,4] 或对象 {a:5} 时,发现 arr3 也发生了变化。所以,concat 只是对数组的第一层进行深拷贝。

方法四:扩展运算符(es6)
 var arr1 = [1, 2, 3]
    var arr2 = [...arr1]
    console.log(arr1) // [1,2,3]
    console.log(arr2) // [1,2,3]
    arr2[0] = 5
    console.log(arr1) // [1,2,3]
    console.log(arr2) // [5,2,3]

const arr1 = [1,2,3,4,5,[6,7,8]];
 const cloneArray = [...arr1];
    cloneArray[0] = 0;
    cloneArray[5].push(9);
    console.log(arr1); // [1,2,3,4,5,[6,7,8,9]]

... 实现的是对象第一层的深拷贝。后面的只是拷贝的引用值。

方法五:JSON.parse、JSON.stringify
 var arr1 = [1, 2, 3]
    var arr2 = JSON.parse(JSON.stringify(arr1))
    console.log(arr1) // [1, 2, 3]
    console.log(arr2) // [1, 2, 3]
    arr2[0] = 5
    console.log(arr1) // [5, 2, 3]
    console.log(arr2) // [5, 2, 3]
    var obj1 = {
        a: 1,
        b: 2
    }

2、合并

方法一:for遍历(不去重)

思路:遍历其中一个数组,把该数组中的所有元素依次添加到另外一个数组中。

var arr1 = [1, 2, 3]
    var arr2 = [2, 3, 4]
    for (var i = 0; i < arr1.length; i++) {
        arr2.push(arr1[i])
    }
    console.log(arr1) // [1,2,3]
    console.log(arr2) // [1,2,3,2,3,4]
方法二:concat方法(不去重)
var arr1 = [1, 2, 3]
    var arr2 = [2, 3, 4]
    var arr3 = arr1.concat(arr2)
    console.log(arr1) // [1,2,3]
    console.log(arr2) // [2,3,4]
    console.log(arr3) // [1,2,3,2,3,4]

concat方法连接a、b两个数组后,a、b两个数组的数据不变,同时会返回一个新的数组。这样当我们需要进行多次的数组合并时,会造成很大的内存浪费,所以这个方法肯定不是最好的。

方法三:apply
var arr1 = [1, 2, 3]
    var arr2 = [2, 3, 4]
    arr1.push.apply(arr1, arr2)
    console.log(arr1) // [1,2,3,2,3,4]
    console.log(arr2) // // [2,3,4]
// 或者
  var arr1 = [1, 2, 3]
    var arr2 = [2, 3, 4]
    Array.prototype.push.apply(arr1, arr2)
    console.log(arr1) // [1,2,3,2,3,4]
    console.log(arr2) // // [2,3,4]

一、对象

1、复制

var obj1 = {
        a: 1,
        b: 2
    }
    var obj2 = obj1
    console.log(obj1); // {a:1,b:2}
    console.log(obj2); // {a:1,b:2}
    obj2.a = 3
    console.log(obj1); // {a:3,b:2}
    console.log(obj2); // {a:3,b:2}

浅copy,两个对象指向同一个地址,一个改变了对象的值,另一个也随之改变。这样的copy并非我们需要的,我们需要的是深copy,两个对象值一样,但是指向不同的地址,一个对象的改变不会影响另一个数组。

方法一:for遍历
var obj1 = {
        a: 1,
        b: 2
    }
    var obj2 = {}
    for (var k in obj1) {
        obj2[k] = obj1[k]
    }
    console.log(obj1);
    console.log(obj2);
    obj2.a = 3
    console.log(obj1);
    console.log(obj2);
方法二:JSON.parse、JSON.stringify
var obj1 = {
        a: 1,
        b: 2
    }
    var obj2 = JSON.parse(JSON.stringify(obj1))
    console.log(obj1); // {a:1,b:2}
    console.log(obj2); // {a:1,b:2}
    obj2.a = 3
    console.log(obj1); // {a:1,b:2}
    console.log(obj2);// {a:3,b:2}

但是,这个方法只能适用于一些简单的情况。例如

 var obj1 = {
        a: 1,
        b: 2,
        setNum: function () {
            console.log('hello world');
        }
    }
    var obj2 = JSON.parse(JSON.stringify(obj1))
    console.log(obj1);
    console.log(obj2);
    obj2.a = 3
    console.log(obj1);
    console.log(obj2);
image.png

发现在obj2 中,有属性丢失了......因为undefined、function、symbol 会在转换过程中被忽略。。。所以,如果对象中含有一个函数时(很常见),就不能用这个方法进行深拷贝

方法三、递归的方法(适用于数组、对象)
function deepClone(source) {
        const targetObj = source.constructor === Array ? [] : {}; // 判断复制的目标是数组还是对象
        for (let keys in source) { // 遍历目标
            if (source.hasOwnProperty(keys)) {
                if (source[keys] && typeof source[keys] === 'object') { // 如果值是对象,就递归一下
                    targetObj[keys] = source[keys].constructor === Array ? [] : {};
                    targetObj[keys] = deepClone(source[keys]);
                } else { // 如果不是,就直接赋值
                    targetObj[keys] = source[keys];
                }
            }
        }
        return targetObj;
    }
    const obj1 = {
        a: 1,
        b: 2,
        setNum: function () {
            console.log('hello world')
        }
    }
    const obj2 = deepClone(obj1)
    console.log(obj1 === obj2)
    obj2.a = 3
    console.log(obj1);
    console.log(obj2);
    var arr1 = [1, 2, 3, {a: 'arr1'}]
    var arr2 = deepClone(arr1)
    console.log(arr1);
    console.log(arr2);
    arr2[3].a = 'arr2'
    console.log(arr1);
    console.log(arr2);
方法四、扩展运算符
const obj1 = {a:1,b:{bb:1}};
 const cloneObj = {...obj1};
    cloneObj.a = 2;
    cloneObj.b.bb = 2;
    console.log(obj1); // {a:1,b:{bb:2}}

... 实现的是对象第一层的深拷贝。后面的只是拷贝的引用值。

方法五、object.assign
 const obj1 = {a:1,b:{bb:1}};
    var obj2 = {}
    Object.assign(obj2,obj1)
    obj2.b.bb = 3
    console.log(obj1); // {a:1,b:{bb:3}}
    console.log(obj2);// {a:1,b:{bb:3}}
var obj3 = {a:1,b:2}
    var obj4 = {}
    Object.assign(obj4,obj3)
    obj4.a = 5
    console.log(obj3); // {a:1,b:2}
    console.log(obj4);// {a:5,b:2}

Object.assign() 拷贝的是属性值。假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值。

总结:

1、赋值运算符 = 实现的是浅拷贝,只拷贝对象的引用值;
2、JavaScript 中数组和对象自带的拷贝方法都是“首层浅拷贝”;
3、JSON.stringify 实现的是深拷贝,但是对目标对象有要求(非 undefined,function);
4、若想真正意义上的深拷贝,请递归。

相关文章

  • 数组、对象的各种处理

    一、数组 1、复制 浅copy,两个数组指向同一个地址,一个改变了数组的值,另一个也随之改变。这样的copy并非我...

  • php的写时复制(和js对比)

    php和js 对于数组 / 对象的处理

  • 笔记:numpy

    NumPy 和它的 ndarray 对象,这个对象为 Python 多维数组提供了高效的存储和处理方法 数组基础向...

  • jQuery处理对象数组

    jQuery删除数组中指定的一条记录 var arrList = ['a','b','c','d']; arrLi...

  • map处理数组对象

    将数组对象的键值作为数组返回

  • NSPredicate

    参考文档1参考文档2NSPredicate 正则表达式的处理 字符串数组的处理 包含对象类数组的处理

  • js对象数组深度去重和深度排序

    js对象数组深度去重和深度排序 要点:使用collect.js处理数组和对象 https://github.com...

  • iOS 获取数组最大值最小值

    如何优雅的处理数组?如何不使用遍历方法处理。 1.获取数组最大值、最小值 保证数组里存储NSNumber对象例如处...

  • 数组 定时器

    数组: 面向对象的方式创建: 直接创建: 数组的常用方法: 数组去重: 字符串处理的方法: var a =char...

  • JavaScript 类数组对象与 arguments

    在 JavaScript 中存在一种特殊的对象,我们称之为类数组对象,其性质与数组相似。我们经常会遇到各种类数组对...

网友评论

      本文标题:数组、对象的各种处理

      本文链接:https://www.haomeiwen.com/subject/tebktqtx.html