JSON反序列化实现一行代码的深克隆

日常逼逼来了,有个小学弟在朋友圈狂秀jquery写的动态切换,再加上比较简洁,一行就能实现,一时间大家都在说.虽然这在项目中是个寻常的操作,不过对于还在学专业课知识的他们来说已经很不错了,我们是不是也需要更有拓展精神呢?接下来就是传说当中的网红深克隆法的讲解.

我先不说,直接发代码,能看懂的就不用看接下来的讲解内容,反正也不难理解

const newObj = JSON.parse(JSON.stringify(oldObj));

讲解慢慢来,我自己也总结一下,现在es6已经在移动端开发用了起来,也有很多现成的工具可以帮助我们将ES5和ES6之前相互相互转化,为了以后大发展,能用es6提供的语法糖就用,干嘛不用呢?

  • JavaScript的基础类型现在包括:undefined,null,boolean,number,string,symbol(es6加的,需要知道),引用类型就是object了.

我们说深克隆,难道有浅克隆吗?为什么说的那么麻烦又晦涩呢?

  • 有,有浅克隆,而且有比较多的办法实现浅克隆,浅克隆的原理我理解为保存指针,就是我们在C,Java中的那种指针,浅克隆的弊端是在克隆的新对象中,我们的相关操作会影响原来的函数.接下来,我就全贴代码了
  // 面向过程编程
        function shallowClone(o) {
            const obj = {};
            // 使用 for ... in 循环遍历数组----for (变量 in 对象)
            for (let key in o) {
                obj[key] = o[key]
            }

            return obj;
        }

        // 从简单的形式理解{}里的定义声明方式:
        const oldObj = {
            a: 1,
            b: [2, 3, 'dfdfdf', 96],
            c: {
                h: {
                    i: 2
                }
            }
        }

        const newObj = shallowClone(oldObj);
        console.log(newObj.c.h, oldObj.c.h);
        if (newObj.c.h === oldObj.c.h) {
            console.log('浅克隆成功');
        }
        newObj.c.h.i = 'i am changed!'
        console.log('oldObj.c.h.i=' + oldObj.c.h.i);


        // 最快的深度克隆,一行代码
        console.log('---------------');
        const JsonObj = JSON.parse(JSON.stringify(oldObj));
        if (JsonObj.a === oldObj.a) {
            console.log('克隆成功');
            JsonObj.a = 'i love you';
            if (JsonObj.a === oldObj.a) {
                console.log('深克隆失败')
            } else {
                console.log('深克隆成功')
            }
        }

怎么样,是不是特别好用,但是这个方法是有弊端的,我只发现了一个,然后问了一下度娘,这坑还挺多的,往下看就知道了,最好自己试一试:

        //构造函数
        function person(pname) {
            // console.log(this);
            this.name = pname;
        }
        const Messi = new person('Messi');

        function say() {
            console.log('you say hi i say hi hi !');
        }
        const testObj = {
            a: say,
            b: new Array(1),
            c: new RegExp('ab+c', 'i'),
            d: Messi
        };

        const tbObj = JSON.parse(JSON.stringify(testObj));
        // 无法复制函数
        console.log(tbObj.a, testObj.a); // undefined [Function: say]
        // 稀疏数组复制错误
        console.log(tbObj.b[0], testObj.b[0]); // null undefined
        // 无法复制正则对象
        console.log(tbObj.c, testObj.c); // {} /ab+c/i
        // 构造函数指向错误
        console.log(tbObj.d.constructor, testObj.d.constructor);
        // [Function: Object] [Function: person]
        const oldObj = {};
        oldObj.a = oldObj;
        const newObj = JSON.parse(JSON.stringify(oldObj));
        console.log(newObj.a, oldObj.a); // TypeError: Converting circular structure to JSON
        // 对象的循环引用会抛出错误.

哈哈,刺激不刺激,惊喜不惊喜