天天看點

【JS】深拷貝實作

一、BUG

WEB平台上一直在刻意的避開深拷貝,一直使用JSON.parse(JSON.stringify(Object))避開深拷貝的問題。知道今天碰見個BUG,JSON将function轉化為了字元串,排到這個BUG時,憔悴…

若是Node.js平台的話,一直現成的輪子等着挑,可惜是WEB,不太敢亂引入,手寫一個<_<

二、深拷貝

/**
 * 深拷貝
 * 支援類型:Boolean,Number,String,null,undefined,Array,Object
 * @param {*} obj 
 */
function deepClone(obj) {

    if (isBaseDataType(obj)) {
        return obj;
    }

    /**
     * 判斷資料類型
     * 不考慮Symbol類型
     * @param {*} obj 
     */
    function judgeType(_obj) {
        return _obj === null ? 'null' : _obj instanceof Array ? 'array' : typeof _obj !== 'object' ? typeof _obj : 'object';
    }

    /**
     * 基本資料類型判斷
     * @param {*} obj 
     */
    function isBaseDataType(_obj) {
        var types = ['boolean', 'number', 'string', 'function', 'null', 'undefined'];
        var type = judgeType(_obj);
        return types.indexOf(type) !== -1;
    }

    /**
     * 數組深拷貝
     * @param {*} _obj 
     * @param {*} res 
     */
    function _cloneArry(_obj) {
        var res = [];
        for (var i = 0, len = _obj.length; i < len; i++) {
            var value = _obj[i];
            if (isBaseDataType(value)) {
                res.push(value);
            } else if (judgeType(value) === 'object') {
                res.push(_cloneObj(value));
            } else if (judgeType(value) === 'array') {
                res.push(_cloneArry(value));
            }
        }
        return res;
    }

    /**
     * 對象深拷貝
     * @param {*} _obj 
     * @param {*} res 
     */
    function _cloneObj(_obj) {
        var res = {};
        for (var attr in _obj) {
            var value = _obj[attr];
            if (isBaseDataType(value)) {
                res[attr] = value;
            } else if (judgeType(value) === 'object') {
                res[attr] = _cloneObj(value);
            } else if (judgeType(value) === 'array') {
                res[attr] = _cloneArry(value);
            }
        }
        return res;
    }

    if (judgeType(obj) === 'array') {
        return _cloneArry(obj);
    } else {
        return _cloneObj(obj);
    }
}
           

另外補充一句:Object.assgin,這個接口真不是深拷貝,也是個不大不小的坑

繼續閱讀