在js中的深複製實現方法

針對本話題,我在2015年5月發佈了新的文章:深刻剖析 JavaScript 的深複製前端

要實現深複製有不少辦法,好比最簡單的辦法有:node

var cloneObj = JSON.parse(JSON.stringify(obj));

上面這種方法好處是很是簡單易用,可是壞處也顯而易見,這會拋棄對象的constructor,也就是深複製以後,不管這個對象本來的構造函數是什麼,在深複製以後都會變成Object。另外諸如RegExp對象是沒法經過這種方式深複製的。git

因此這裏我將介紹一種,我自認爲很優美的深複製方法,固然可能也存在問題。若是你發現了個人實現方法有什麼問題,請及時讓我知道~github

先決條件:
1. 對於任何對象,它可能的類型有Boolean, Number, Date, String, RegExp, Array 以及 Object(全部自定義的對象全都繼承於Object
2. 咱們必須保留對象的構造函數信息(從而使新對象可使用定義在prototype上的函數)segmentfault

最重要的一個函數:函數

Object.prototype.clone = function () {
    var Constructor = this.constructor;
    var obj = new Constructor();

    for (var attr in this) {
        if (this.hasOwnProperty(attr)) {
            if (typeof(this[attr]) !== "function") {
                if (this[attr] === null) {
                    obj[attr] = null;
                }
                else {
                    obj[attr] = this[attr].clone();
                }
            }
        }
    }
    return obj;
};

定義在Object.prototype上的clone()函數是整個方法的核心,對於任意一個非js預約義的對象,都會調用這個函數。而對於全部js預約義的對象,如Number,Array等,咱們就要實現一個輔助clone()函數來實現完整的克隆過程:this

/* Method of Array*/
Array.prototype.clone = function () {
    var thisArr = this.valueOf();
    var newArr = [];
    for (var i=0; i<thisArr.length; i++) {
        newArr.push(thisArr[i].clone());
    }
    return newArr;
};

/* Method of Boolean, Number, String*/
Boolean.prototype.clone = function() { return this.valueOf(); };
Number.prototype.clone = function() { return this.valueOf(); };
String.prototype.clone = function() { return this.valueOf(); };

/* Method of Date*/
Date.prototype.clone = function() { return new Date(this.valueOf()); };

/* Method of RegExp*/
RegExp.prototype.clone = function() {
    var pattern = this.valueOf();
    var flags = '';
    flags += pattern.global ? 'g' : '';
    flags += pattern.ignoreCase ? 'i' : '';
    flags += pattern.multiline ? 'm' : '';
    return new RegExp(pattern.source, flags);
};

可能直接定義在預約義對象的方法上,讓人感受會有些問題。但在我看來這是一種優美的實現方式。prototype

同時我也在開發一個插件,主要的思想也就是擴展預約義對象的方法。
這個插件叫JustJSGithub項目地址
有如下一些特性:
1. 同時支持Web前端和node.js使用。
2. 直接對預約義對象的方法進行擴展
3. 使用 J(function(){...}) 語句塊,決不污染全局命名空間。
目前只寫了一小部分,同時也寫了些簡單的文檔,有興趣的同窗能夠看一下,也能夠加入我,Fork個人項目,喜歡的同窗還能夠給Star插件

相關文章
相關標籤/搜索