手写JS深拷贝

源码:

支持拷贝String、Number、Boolean、Null、Undefined、Object(Function、Array、RegExp、Date、环)

class deepCloner {
    constructor() {
        this.cache = []
    }
    clone(source) {
        if (source instanceof Object) {
            const cacheDist = this.findCache(source)
            if (cacheDist) {
                return cacheDist
            } else {
                let dist
                if (source instanceof Array) {// 数组的情况
                    dist = new Array()
                } else if (source instanceof Function) {// 函数的情况
                    dist = function() {
                        return source.apply(this, arguments)
                    }
                } else if (source instanceof Date) {// date的情况
                    dist = new Date(source)
                } else if (source instanceof RegExp) {// RegExp的情况
                    dist = new RegExp(source.source, source.flags)// 分别截取正则的前后段
                } else {
                    dist = new Object()
                }
                this.cache.push([source, dist]);// 环的情况
                for (let key in source) {
                    dist[key] = this.clone(source[key])
                }
                return dist
            }
        }
        return source
    }

    findCache(source) {
        for (let i=0; i<this.cache.length; i++) {
            if (this.cache[i][0] === source) {
                return this.cache[i][1]
            }
        }
        return undefined
    }
}

module.exports = deepCloner

测试代码:

const chai = require("chai")
const sinon = require("sinon")
const sinonChai = require("sinon-chai")
chai.use(sinonChai);

const assert = chai.assert
const deepCloner = require("../src/index")

describe("deepCloner", ()=>{
    it('是一个类', ()=>{
        assert.isFunction(deepCloner)
    })
    it('测试深拷贝基础类型', ()=>{
        const number = 123
        const number2 = new deepCloner().clone(number)
        assert(number === number2)
        const string = '字符串'
        const string2 = new deepCloner().clone(string)
        assert(string === string2)
        const boolean = true
        const boolean2 = new deepCloner().clone(boolean)
        assert(boolean === boolean2)
        const un = undefined
        const un2 = new deepCloner().clone(un)
        assert(un === un2)
        const nu = null
        const nu2 = new deepCloner().clone(nu)
        assert(nu === nu2)
        const sym = Symbol()
        const sym2 = new deepCloner().clone(sym)
        assert(sym === sym2)
    })
})

describe('对象', ()=>{
    it('能够复制普通对象', ()=> {
        const a = {name:'yy', child:{name: 'yyy'}}
        const a2 = new deepCloner().clone(a)
        assert(a !== a2)
        assert(a.name === a2.name)
        assert(a.child !== a2.child)
        assert(a.child.name === a2.child.name)
    });
    it('能够复制数组对象', ()=> {
        const a = [[11,12,13],[21,22,23],[31,32,33]]
        const a2 = new deepCloner().clone(a)
        assert(a !== a2)
        assert.deepEqual(a, a2) //检测2个数组中的每个值
    });
    it('能够复制函数', ()=> {
        const a = function fn(a, b) {
            return a+b
        }
        a.xx = {yy: {zz: 1}}
        const a2 = new deepCloner().clone(a)
        assert(a.xx !== a2.xx)
        assert(a.xx.yy !== a2.xx.yy)
        assert(a.xx.yy.zz === a2.xx.yy.zz)
        assert(a !== a2)
        assert(a(1,2) === a2(1,2))
    });
    it('环也能复制', ()=> {
        const a = {name: 'YY'}
        a.self = a
        const a2 = new deepCloner().clone(a)
        assert(a !== a2)
        assert(a.name === a2.name)
        assert(a.self !== a2.self)
    });
    it('能够复制Date', ()=> {
        const a = {name: 'YY'}
        a.self = a
        const a2 = new deepCloner().clone(a)
        assert(a !== a2)
        assert(a.name === a2.name)
        assert(a.self !== a2.self)
    });
    it('能够复制RegExp', ()=> {
        const a = new RegExp('/hi\d+/', 'gi')
        a.obj = {name: 'XX'}
        const a2 = new deepCloner().clone(a)
        assert(a.source === a2.source);
        assert(a.flags === a2.flags);
        assert(a !== a2);
        assert(a.obj !== a2.obj);
        assert(a.obj.name === a2.obj.name);
    });
    it('能够复制日期', ()=> {
        const a = new Date()
        a.obj = {name: 'XX'}
        const a2 = new deepCloner().clone(a)
        assert(a.source === a2.source);
        assert(a.flags === a2.flags);
        assert(a !== a2);
        assert(a.obj !== a2.obj);
        assert(a.obj.name === a2.obj.name);
    });
})

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值