most-elegant-way-to-clone-a-javascript-object

To do this for any object in JavaScript will not be simple or straightforward. You will run into the problem of erroneously picking up attributes from the object's prototype that should be left in the prototype and not copied to the new instance. If, for instance, you are adding aclonemethod toObject.prototype, as some answers depict, you will need to explicitly skip that attribute. But what if there are other additional methods added toObject.prototype, or other intermediate prototypes, that you don't know about? In that case, you will copy attributes you shouldn't, so you need to detect unforeseen, non-local attributes with thehasOwnPropertymethod.

In addition to non-enumerable attributes, you'll encounter a tougher problem when you try to copy objects that have hidden properties. For example,prototypeis a hidden property of a function. Also, an object's prototype is referenced with the attribute__proto__, which is also hidden, and will not be copied by a for/in loop iterating over the source object's attributes. I think__proto__might be specific to Firefox's JavaScript interpreter and it may be something different in other browsers, but you get the picture. Not everything is enumerable. You can copy a hidden attribute if you know its name, but I don't know of any way to discover it automatically.

Yet another snag in the quest for an elegant solution is the problem of setting up the prototype inheritance correctly. If your source object's prototype isObject, then simply creating a new general object with {} will work, but if the source's prototype is some descendant ofObject, then you are going to be missing the additional members from that prototype which you skipped using thehasOwnPropertyfilter, or which were in the prototype, but weren't enumerable in the first place. One solution might be to call the source object'sconstructorproperty to get the initial copy object and then copy over the attributes, but then you still will not get non-enumerable attributes. For example, aDateobject stores its data as a hidden member:

functionclone(obj){if(null==obj||"object"!=typeofobj)returnobj;varcopy=obj.constructor();for(varattrinobj){if(obj.hasOwnProperty(attr))copy[attr]=obj[attr];}returncopy;}vard1=newDate();/* Wait for 5 seconds. */varstart=(newDate()).getTime();while((newDate()).getTime()-start<5000);vard2=clone(d1);alert("d1 = "+d1.toString()+"\nd2 = "+d2.toString());

The date string for d1 will be 5 seconds behind that of d2. A way to make one Date the same as another is by calling thesetTimemethod, but that is specific to the Date class. I don't think there is a bullet-proof general solution to this problem, though I would be happy to be wrong!

When I had to implement general deep copying I ended up compromising by assuming that I would only need to copy a plainObject,Array,Date,String,Number, orBoolean. The last 3 types are immutable, so I could perform a shallow copy and not worry about it changing. I further assumed that any elements contained in Object or Array would also be one of the 6 simple types in that list. This can be accomplished with code like the following:

functionclone(obj){varcopy;// Handle the 3 simple types, and null or undefinedif(null==obj||"object"!=typeofobj)returnobj;// Handle Dateif(objinstanceofDate){copy=newDate();copy.setTime(obj.getTime());returncopy;}// Handle Arrayif(objinstanceofArray){copy=[];for(vari=0,len=obj.length;i

The above function will work adequately for the 6 simple types I mentioned, as long as the data in the objects and arrays form a tree structure. That is, there isn't more than one reference to the same data in the object. For example:

// This would be cloneable:vartree={"left":{"left":null,"right":null,"data":3},"right":null,"data":8};// This would kind-of work, but you would get 2 copies of the// inner node instead of 2 references to the same copyvardirectedAcylicGraph={"left":{"left":null,"right":null,"data":3},"data":8};directedAcyclicGraph["right"]=directedAcyclicGraph["left"];// Cloning this would cause a stack overflow due to infinite recursion:varcylicGraph={"left":{"left":null,"right":null,"data":3},"data":8};cylicGraph["right"]=cylicGraph;

It will not be able to handle any JavaScript object, but it may be sufficient for many purposes as long as you don't assume that it will just work for anything you throw at it.

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末购岗,一起剝皮案震驚了整個濱河市汰聋,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌喊积,老刑警劉巖烹困,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異乾吻,居然都是意外死亡髓梅,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進店門绎签,熙熙樓的掌柜王于貴愁眉苦臉地迎上來枯饿,“玉大人,你說我怎么就攤上這事诡必∩莘剑” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蟋字。 經(jīng)常有香客問我稿蹲,道長,這世上最難降的妖魔是什么愉老? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任场绿,我火速辦了婚禮剖效,結(jié)果婚禮上嫉入,老公的妹妹穿的比我還像新娘。我一直安慰自己璧尸,他們只是感情好咒林,可當我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著爷光,像睡著了一般垫竞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蛀序,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天欢瞪,我揣著相機與錄音,去河邊找鬼徐裸。 笑死遣鼓,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的重贺。 我是一名探鬼主播骑祟,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼气笙!你這毒婦竟也來了次企?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤潜圃,失蹤者是張志新(化名)和其女友劉穎缸棵,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谭期,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡堵第,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了崇堵。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片型诚。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡鸳劳,死狀恐怖狰贯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤涵紊,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布傍妒,位于F島的核電站,受9級特大地震影響摸柄,放射性物質(zhì)發(fā)生泄漏颤练。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一驱负、第九天 我趴在偏房一處隱蔽的房頂上張望嗦玖。 院中可真熱鬧,春花似錦跃脊、人聲如沸宇挫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽器瘪。三九已至,卻和暖如春绘雁,著一層夾襖步出監(jiān)牢的瞬間橡疼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工庐舟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留欣除,地道東北人。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓继阻,卻偏偏與公主長得像耻涛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子瘟檩,可洞房花燭夜當晚...
    茶點故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內(nèi)容