javascript javascript中的重复对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13287297/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 18:18:56  来源:igfitidea点击:

Duplicate object in javascript

javascriptobject

提问by user1801625

I see two ways to duplicate objects

我看到了两种复制对象的方法

1.

1.

var a={c:1}
var b=a;
alert(b.c);//alert 1

2.

2.

var a={c:2};
var b={};
for (i in a)
{b[i]=a[i];} 
alert(b.c);//alert 1

The first are shorter than the second so what is the efficiency in the second example?

第一个比第二个短那么第二个例子的效率是多少?

采纳答案by Sirko

The first does not create a copy, but just copies the reference, so aand bpoint towards the same object after the operation.

先不创建一个副本,但只是复制引用,所以ab对术后同一物点。

In the second case, however, each attribute is copied separately, thus creating a "real" copy of the object in a(as long as there are just primitive types in the properties, else you got the same problem at a deeper level).

然而,在第二种情况下,每个属性都被单独复制,从而创建了对象的“真实”副本a(只要属性中只有原始类型,否则在更深层次上会遇到相同的问题)。

So in the first case if you change b.cthen a.cwill also change, while in the second case it wont.

因此,在第一种情况下,如果您更改,b.c那么a.c也会更改,而在第二种情况下则不会。

回答by andlrc

In the first version you don't duplicate/clone the object you simply make a extra reference to it:

在第一个版本中,您不复制/克隆对象,您只需对其进行额外引用:

var a = { a: 1 };
var b = a;
b.a = 2;

console.log(a.a); // 2;

To clone an object there is numbers of libraries that can do that for you:

要克隆一个对象,有许多库可以为您做到这一点:

var b = $.extend({}, a); // Make a shallow clone (jQuery)
var b _.extend({}, a); // Make a shallow clone (underscore.js)

var b = $.extend(true, {}, a); // Make a deep clone (jQuery);

Or you can do it natively:
Simple clone:

或者您可以在本机进行:
简单克隆:

var b = {};
var prop;

for (prop in a) {
    b[prop] = a[prop];
}


Scratch of a deep clone function:

深度克隆功能的划痕:

function deepClone(obj) {
    var r;
    var i = 0,
    var len = obj.length;
    // string, number, boolean
    if (typeof obj !== "object") { 
        r = obj;
    }
    // Simple check for array
    else if ( len ) { 
        r = [];
        for ( ; i < len; i++ ) {
            r.push( deepClone(obj[i]) );
        }
    } 
    // Simple check for date
    else if ( obj.getTime ) { 
        r = new Date( +obj );
    }
    // Simple check for DOM node
    else if ( obj.nodeName ) { 
        r = obj;
    }
    // Object
    else { 
        r = {};
        for (i in obj) {
            r[i] = deepClone(obj[i]);
        }
    }

    return r;
}

回答by Elias Van Ootegem

As others have stated here: the first assignment, assigns a new reference to an existing object, the second performs a shallow copy.
By shallowI mean: only the base object will be copied, there is no recursion:

正如其他人在这里所说的那样:第一个赋值,为现有对象分配一个新的引用,第二个执行一个浅拷贝
我的意思是:只有基本对象将被复制,没有递归:

var a = {some:'propery',
         another:{might:'be',
                  an: 'object, too'}
        };
var b = {};
for(var p in a)
{
    b[p] = a[p];
}
b.some = 'b\'s own property';
console.log(a.some);//property -> unaltered
console.log(b.some);//b's own property --> separate entities
b.another.might = 'foo';
console.log(a.another.might);//foo ==> b.another references a.another

To solve this issue, you would be forgiven to think that a simple recursive function would suffice:

为了解决这个问题,你可以认为一个简单的递归函数就足够了:

var cloneObj = function(o)
{
    var p,r = {};
    for (p in o)
    {//omitting checks for functions, date objects and the like
        r[p] = (o[p] instanceof Object ? cloneObj(o[p]) : o[p]);
    }
};

But be weary of circular references!

但是要厌倦循环引用

//assume a is the same object as above
a._myself = a;//<- a references itself

This will produce endless recursion, aka a deadlock scenario, unless you add a check for just such cases:

这将产生无休止的递归,也就是死锁场景,除非您仅针对此类情况添加检查:

var cloneObj = function(o)
{
    var p,r = {};
    for (p in o)
    {//Needs a lot more work, just a basic example of a recursive copy function
        switch(true)
        {
            case o[p] instanceof Function:
                r[p] = o[p];
            break;
            case o[p] instanceof Date:
                r[p] = new Date(o[p]);
            break;
            case o === o[p]:
            //simple circular references only
            //a.some.child.object.references = a; will still cause trouble
                r[p] = r;
            break;
            case o[p] instanceof Array:
                r[p] = o[p].slice(0);//copy arrays
            break;
            default:
                r[p] = o[p] instanceof Object ? cloneObj(o[p]) : o[p];
        }
    }
    return r;
};

Now, this is quite verbose, and in most cases utter overkill, if all you want are two objects with the same data, but can be altered independently (ie don't reference the same object in memory), all you need is 1 line of code:

现在,这是相当冗长的,而且在大多数情况下完全是矫枉过正,如果你想要的只是具有相同数据的两个对象,但可以独立更改(即不要在内存中引用同一个对象),那么你只需要 1 行代码:

var a = {some:'propery',
         another:{might:'be',
                  an: 'object, too'}
        };
var b = JSON.parse(JSON.stringify(a));

Bottom line: assigning a reference is certainly more efficient: it doesn't require the object constructor to be called a second time, nor does it require an additional copy of any of the constants.
The downside is: you end up with a single object and might inadvertently change/delete something that you assume is still there when you're using the other reference (delete b.some;/*some time later*/a.some.replace(/p/g,'q');//<--error)

底线:分配引用肯定更有效:它不需要第二次调用对象构造函数,也不需要任何常量的额外副本。
缺点是:您最终会得到一个对象,并且可能会无意中更改/删除您在使用其他引用时认为仍然存在的内容 ( delete b.some;/*some time later*/a.some.replace(/p/g,'q');//<--error)

回答by Andras Zoltan

The first copies the reference and does not duplicatethe object, the second creates a new reference and then copies the members (which, in turn, if they are references will just copy the references only).

第一个复制引用而不复制对象,第二个创建一个新的引用,然后复制成员(反过来,如果它们是引用,则只会复制引用)。

You might want to look at this other SO - Does Javascript equal sign reference objects or clones them?

您可能想看看其他 SO - Javascript 等号引用对象还是克隆它们?

It's not a question of efficiency it's ultimately about correctness. If you need to share a reference to an object between different code blocks (e.g. so that multiple pieces of code can share the same object) - then you simply rely on the fact that javascript passes by reference.

这不是效率问题,它最终是关于正确性的。如果您需要在不同的代码块之间共享对一个对象的引用(例如,以便多段代码可以共享同一个对象) - 那么您只需依赖 javascript 通过引用传递的事实。

If, however, you need to copy an object between methods - then you might be able to use your simple example in your second code block (if your objects don't have other 'objects' in them), otherwise you might have to implement a deep-clone (see How to Deep clone in javascript, and pay attention to the answer(s) there - it's not a trivial business).

但是,如果您需要在方法之间复制对象 - 那么您可以在第二个代码块中使用您的简单示例(如果您的对象中没有其他“对象”),否则您可能必须实现深度克隆(请参阅如何在 javascript 中进行深度克隆,并注意那里的答案 - 这不是一件小事)。