对象深拷贝后删除属性问题??

llyy112233 2011-03-25 10:50:38
代码1 :



<script type="text/javascript">
//对象深拷贝函数
var cloneAll = function (o){
function clonePrototype(){}
clonePrototype.prototype = o;
var obj = new clonePrototype();
for(var elements in obj){
if (typeof(obj[elements]) == "object") {
obj[elements] = cloneAll(obj[elements]);
}
}
return obj;
}

var obj = {
m : {o : {l : 1}, p : 1},
n : 2
}

var test = cloneAll(obj);

function del(attr, o) {
delete o[attr];
}


del('m', test);

for (var attr in test) {
alert('test : ' + attr + ' ' + test[attr]);
}

del('m', obj);

for (var attr in obj) {
alert('obj : ' + attr + ' ' + obj[attr]);
}


</script>




代码2 ,换一下删除的顺序:


<script type="text/javascript">
var cloneAll = function (o){
function clonePrototype(){}
clonePrototype.prototype = o;
var obj = new clonePrototype();
for(var elements in obj){
if (typeof(obj[elements]) == "object") {
obj[elements] = cloneAll(obj[elements]);
}
}
return obj;
}

var obj = {
m : {o : {l : 1}, p : 1},
n : 2
}

var test = cloneAll(obj);

function del(attr, o) {
delete o[attr];
}

del('m', obj);

for (var attr in obj) {
alert('obj : ' + attr + ' ' + obj[attr]);
}

del('m', test);

for (var attr in test) {
alert('test : ' + attr + ' ' + test[attr]);
}

</script>



代码1和代码2在IE中表现均正常,但是在chrome中却变现得很奇怪。

代码1先删除复制的对象test的属性m没有删除掉,但源对象obj的m却删除掉了。 这是为什么????

代码2先删除源对象obj的m后,test的m也正常删除了。。

要的效果就是不动obj对象,在chrome中删除掉 test的属性。

这位高手看看要怎么解决。。??
...全文
255 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
llyy112233 2011-03-31
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 firebugdotname 的回复:]
"我觉得test的contructor.prototype里面已经有个m属性了,删除掉之后"


你并没有删除掉 test.constructor.prototpe 的 属性
你删除掉的是 test 的属性。

delete test[pro] 不等于 delete test.constructor.prototype[pro]

这两个删除操作的对象是不一样的。
[/Quote]

确实不一样,谢谢, 问题已解决。
firebugdotname 2011-03-26
  • 打赏
  • 举报
回复

function deepClone(obj){
var result = {};

for(var p in obj){
if(obj[p] instanceof Array){
result[p] = obj[p].slice();
continue;
}

if(obj[p] && typeof obj[p] == "object"){
result[p] = arguments.callee.call(null, obj[p]);
continue;
}

result[p] = obj[p];
}

return result;
}

firebugdotname 2011-03-26
  • 打赏
  • 举报
回复
先说代码1



var b = {name: 'ethan'};
var a = cloneAll(b)
//代码执行到这里的时候, 对象b成为对象a构造函数的原型链
// clonePrototype.prototype = o;
// var obj = new clonePrototype();
// 由这两行代码实现





delete a.name
//删除对象a的name属性 (其实对象a本身不存在name属性,name属性存在于a的构造函数原型中,即对象b)




alert(a.name)
//查询对象a的name属性,没找到,于是去对象a构造函数的原型(即b)中查询,找到name属性,返回'ethan';



至于楼主说的在ie中的行为和chrome中不大一样我手上只有ie9,测试的结果是一样。不知道你用的是什么版本的IE。



代码2中,先删除了原型的属性,所以在实例对象上没有找到该属性,这个行为也是预料之中的。



example:

function F(){}
F.prototype = {list: []}

alert((new F).list === (new F).list)
alert([] === [])

firebugdotname 2011-03-26
  • 打赏
  • 举报
回复
"我觉得test的contructor.prototype里面已经有个m属性了,删除掉之后"


你并没有删除掉 test.constructor.prototpe 的 属性
你删除掉的是 test 的属性。

delete test[pro] 不等于 delete test.constructor.prototype[pro]

这两个删除操作的对象是不一样的。
llyy112233 2011-03-26
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 firebugdotname 的回复:]
JScript code

function deepClone(obj){
var result = {};

for(var p in obj){
if(obj[p] instanceof Array){
result[p] = obj[p].slice();
continue;
……
[/Quote]

谢谢,代码可用。
没想到slice函数居然可以连第一个参数都可以不用传。
llyy112233 2011-03-26
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 hnxxwyq 的回复:]
JScript code

代码1
// 理解当前object和原型链的关系,好像 你父亲的钱 和 你的钱
del('m', test);

// 你的钱花完了,不代表你父亲的钱花完了

for (var attr in test) {
alert('test : ' + attr + ' ' + test[attr]);
}

// 你父亲的钱也花完了……
[/Quote]

比喻得很形象,谢谢。
我没有考虑到原型链继承的问题。 学习了。
llyy112233 2011-03-26
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 firebugdotname 的回复:]
先说代码1


JScript code


var b = {name: 'ethan'};
var a = cloneAll(b)
//代码执行到这里的时候, 对象b成为对象a构造函数的原型链
// clonePrototype.prototype = o;
// var obj = new clonePrototype();
// 由这两行代码实现





……
[/Quote]

我用的是IE8的,我觉得test的contructor.prototype里面已经有个m属性了,删除掉之后,它会去找contructor.prototype.prototype里面的m属性,也就是obj的contructor.prototype里面的属性。

验证如下:如果只删除掉obj的属性m,test的属性m还是存在的。
lazyboy_wu 2011-03-26
  • 打赏
  • 举报
回复
或者你可以改变原型链



// 删除test.m 以后
del('m', test);

// 改变test的原型链到默认Object上。。但是以后和obj就一点关系都没有了
test.constructor.prototype = new Object();
test.constructor = Object;
lazyboy_wu 2011-03-26
  • 打赏
  • 举报
回复

代码1
// 理解当前object和原型链的关系,好像 你父亲的钱 和 你的钱
del('m', test);

// 你的钱花完了,不代表你父亲的钱花完了

for (var attr in test) {
alert('test : ' + attr + ' ' + test[attr]);
}

// 你父亲的钱也花完了,你们家开始穷了
del('m', obj);

for (var attr in obj) {
alert('obj : ' + attr + ' ' + obj[attr]);
}


// 代码2

// 你父亲的钱没有了,仅代表你不能再继承你父亲的家产了
del('m', obj);

for (var attr in obj) {
alert('obj : ' + attr + ' ' + obj[attr]);
}

// 你的钱花完了 又不能从你父亲那里拿钱,只能受穷了
del('m', test);

for (var attr in test) {
alert('test : ' + attr + ' ' + test[attr]);
}

// 你觉得你既然是你父亲的儿子,你花完钱了,那么(在你父亲有钱的前提下)你不想继承你父亲的钱,这合理吗?
// 答案很简单,只要你不是你父亲的儿子就可以实现
// 同理,只要不用原型链,仅对象复制可以实现你要的效果
for(var elements in o){ // 而不是用你的克隆对象实现
}

87,910

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧