对JScript对象的实例Clone的一个实现

此博客为转载内容,转载自https://www.cnblogs.com/birdshome/archive/2005/02/22/107221.html ,原内容可能与JavaScript相关。
    刚才看见 cmbscqhd关于' JS继承问题的研究',发现他的继承方法的问题出在对对象使用了shallow copy ( this[i] = _childClass.prototype[i];)上。不过从他的代码中我发现了一个实现Clone很sexy的方法,于是写一个JScript类实例的的deep clone方法,和对JScript所支持对象(数据类型)的Clone详细比较。

    实现Clone最关键的就是要创建一个和原对象类型相同的对象,不然还叫什么Clone呢?然后再把原对象里的值Copy到目标对象,如果遇到值本身是对象的,还需要继续递归创建和复制数据。

    JScript对象实例的Clone方法代码如下:
ExpandedBlockStart.gif ContractedBlock.gif < script  language ="javascript" > dot.gif
InBlock.gifObject.prototype.Clone 
= function()
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif    
var objClone = new this.constructor();
InBlock.gif    
for ( var key in this )
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
if ( objClone[key] != this[key] )
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif
InBlock.gif            
if ( typeof(this[key]) == 'object' )
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif
InBlock.gif                objClone[key] 
= this[key].Clone();
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                objClone[key] 
= this[key];
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
if ( !objClone || ('' + objClone) == '' )
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return (new String(this+ objClone) ? this : objClone;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
else
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        objClone.toString 
= this.toString;
InBlock.gif        
return objClone; 
ExpandedSubBlockEnd.gif    }
 
ExpandedBlockEnd.gif}
    
None.gif
</ script >

    这段代码中最关键的两点就是: var  objClone  =   new   this .constructor();和objClone[key] = this[key].Clone();。一个完成相同对象创建,一个完成了deep clone。最后那个判断到底是返回 this还是返回objClone,是用来对 对象类型或空Array的一个优化。这个Clone方法对所有(不包括Function、Global和Math)JScript对象实例的Clone效果分析如下:
   JScriptClone.gif

    显现对于值类型这个Clone方法不能很好的工作:(,还有一个比较特殊的对象类型,就是Date,它也不能被正常的Clone。不过这个不是很严重的问题,要在Clone方法里面去判断被Clone的对象是不是Date、Boolean和Number相对来说是很容易的。我没有加到这个方法中去是为了保持这个方法的清爽,因为我们值类型本身是不存在Clone问题的,赋值即就是Clone了。

    附Clone方法的测试源代码:
None.gif < html >
None.gif
< head >
None.gif    
< title > JScript Inherit Research </ title >
None.gif    
< meta  name ="author"  content ="cmbscqhd;birdshome@博客园"   />
None.gif
</ head >
None.gif
< body >
ExpandedBlockStart.gifContractedBlock.gif    
< script  language ="javascript" > dot.gif
InBlock.gif    Object.prototype.Clone 
= function()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif         
var objClone = new this.constructor();
InBlock.gif         
for ( var key in this )
ExpandedSubBlockStart.gifContractedSubBlock.gif         
dot.gif{
InBlock.gif             
if ( objClone[key] != this[key] )
ExpandedSubBlockStart.gifContractedSubBlock.gif             
dot.gif
InBlock.gif                  
if ( typeof(this[key]) == 'object' )
ExpandedSubBlockStart.gifContractedSubBlock.gif                  
dot.gif
InBlock.gif                       objClone[key] 
= this[key].Clone();
ExpandedSubBlockEnd.gif                  }

InBlock.gif                  
else
ExpandedSubBlockStart.gifContractedSubBlock.gif                  
dot.gif{
InBlock.gif                       objClone[key] 
= this[key];
ExpandedSubBlockEnd.gif                  }

ExpandedSubBlockEnd.gif             }

ExpandedSubBlockEnd.gif         }

InBlock.gif         
if ( !objClone || ('' + objClone) == '' )
ExpandedSubBlockStart.gifContractedSubBlock.gif         
dot.gif{
InBlock.gif              
return (new String(this+ objClone) ? this : objClone;
ExpandedSubBlockEnd.gif         }

InBlock.gif         
else
ExpandedSubBlockStart.gifContractedSubBlock.gif         
dot.gif{
InBlock.gif              objClone.toString 
= this.toString;
InBlock.gif              
return objClone; 
ExpandedSubBlockEnd.gif         }
 
ExpandedSubBlockEnd.gif    }
    
ExpandedBlockEnd.gif    
</ script >
ExpandedBlockStart.gifContractedBlock.gif    
< script  language ="javascript" > dot.gif
InBlock.gif    document.write(
"<table border='1' style='border-collapse: collapse;'>"
InBlock.gif         
+ '<tr><th>Data Type</th><th>Original</th><th>Cloned'
InBlock.gif         
+ '</th><th>Modified</th><th>Status</th></tr>');
InBlock.gif    
var Render = function(type, original, cloned, modified, isSuccess)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif         
var str = '<tr><td>+ type + '</td><td>+ original + '</td><td>'
InBlock.gif             
+ cloned + '</td><td>+ modified + '</td><td align="center">'
InBlock.gif             
+ '<span style="color:' + (isSuccess ? 'blue' : 'red') + ';">
InBlock.gif             
+ (isSuccess ? ':):):)' : ':(:(:(') + '</span></td></tr>';
InBlock.gif        document.write(str);
ExpandedSubBlockEnd.gif    }
    
InBlock.gif
InBlock.gif    
var obj =
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif         abc : 'abc',
InBlock.gif         faint : ['f', 'a', 'i', 'n', 't'],
InBlock.gif         toString : 
function()
ExpandedSubBlockStart.gifContractedSubBlock.gif         
dot.gif{
InBlock.gif              
return 'abc:' + this.abc + ', faint:[' + this.faint + ']';
ExpandedSubBlockEnd.gif         }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
var objClone = obj.Clone();
InBlock.gif    
var objClone2 = obj.Clone();
InBlock.gif    objClone2.abc 
= 'def';
InBlock.gif    
for ( var i=0 ; i < objClone2.faint.length ; ++i ) objClone2.faint[i] = '-'; 
InBlock.gif    Render('Object', obj, objClone, objClone2, 
true);
InBlock.gif   
InBlock.gif    
var dt = new Date();
InBlock.gif    
for ( var i=0 ; i < 300000 ; i++ ) new Object(); 
InBlock.gif    
var dtClone = dt.Clone();
InBlock.gif    
for ( var i=0 ; i < 300000 ; i++ ) new Object(); 
InBlock.gif    
var dtClone2 = dt.Clone();
InBlock.gif    dtClone2.setYear(
2006);
InBlock.gif    Render('Date', dt.getTime(), dtClone.getTime(), dtClone2.getTime(), 
false);
InBlock.gif    
InBlock.gif    
var ary = ['a', 'r', 'y'];
InBlock.gif    
var aryClone = ary.Clone();
InBlock.gif    
var aryClone2 = ary.Clone();
InBlock.gif    aryClone2.push('
!!!'); 
InBlock.gif    Render('Array', ary, aryClone, aryClone2, 
true);
InBlock.gif   
InBlock.gif    
var aryEx = [];
InBlock.gif    
var aryExClone = aryEx.Clone();
InBlock.gif    
var aryExClone2 = aryEx.Clone();
InBlock.gif    aryExClone2.push('ary'); 
InBlock.gif    Render('Array(
null)', aryEx, aryExClone, aryExClone2, true);
InBlock.gif
InBlock.gif    
var str = 'faint';
InBlock.gif    
var strClone = str.Clone();
InBlock.gif    
var strClone2 = str.Clone();
InBlock.gif    strClone2 
= 'layala'; 
InBlock.gif    Render('String', str, strClone, strClone2, 
true);
InBlock.gif    
InBlock.gif    
var bool = true;     
InBlock.gif    
var boolClone = bool.Clone();
InBlock.gif    
var boolClone2 = bool.Clone();
InBlock.gif    boolClone2 = false;
InBlock.gif    Render('Boolean', bool, boolClone, boolClone2, 
false);
InBlock.gif     
InBlock.gif    
var num = 100;
InBlock.gif    
var numClone = num.Clone();
InBlock.gif    var numClone2 = num.Clone();
InBlock.gif    Render('Number', num, numClone, numClone2, false);
InBlock.gif    
InBlock.gif    
var err = new Error(100, 'error!');
InBlock.gif    
var errClone = err.Clone();
InBlock.gif    
var errClone2 = err.Clone(); 
InBlock.gif    errClone2.number 
= 10000;
InBlock.gif    errClone2.message 
= 'ERROR!'; 
ExpandedSubBlockStart.gifContractedSubBlock.gif    Error.prototype.ToString 
= function() dot.gifreturn this.number + ', ' + this.message; }
InBlock.gif    Render('Error', err.ToString(), errClone.ToString(), errClone2.ToString(), 
true);
InBlock.gif    
InBlock.gif    document.write('
</table>'); 
InBlock.gif    
// Function Global, Math ,Regex
ExpandedBlockEnd.gif
    
</ script >
None.gif
</ body >
None.gif
</ html > None.gif

转载于:https://www.cnblogs.com/birdshome/archive/2005/02/22/107221.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值