6

这是我的老问题的延续

这是我创建一个新学生对象的函数:

function student(id, name, marks, mob, home){
    this.id = id;
    this.name = name;
    this.marks = marks;
    this.contacts = {};
    this.contacts.mob = mob;
    this.contacts.home = home;

    this.toContactDetailsString = function(){
        return this.name +':'+ this.mob +', '+ this.home
    }
}

我想在对象内部初始化时创建对象的副本:我想出了这个:

function student(id, name, marks, mob, home){
    this.id = id;
    this.name = name;
    this.marks = marks;
    this.contacts = {};
    this.contacts.mob = mob;
    this.contacts.home = home;

    this.toContactDetailsString = function(){
        return this.name +':'+ this.mob +', '+ this.home
    }
    this.baseCopy = this; //Not sure about this part
}

但问题是它给了我baseCopy中当前对象副本的无限循环;而且,当我更新对象的任何属性时,它也会自动更新。

1. 这怎么可能,我可以在创建对象时在该对象内部保留具有初始值的对象的副本?

2.是否可以不复制功能

3.我很想知道如果没有硬编码属性名称和使用纯JS这是否可能

4

4 回答 4

3

您不是通过说来创建副本

this.baseCopy = this;,您只是设置对这个内部变量的引用。所以 baseCopy 也指向同一个对象

您需要创建一个方法,该方法将从传递的学生对象返回一个新的学生对象,然后将其存储为 BaseCopy

于 2012-12-20T09:44:04.790 回答
3

很像我对您上一个问题的回答,您可以使用此代码复制对象及其嵌套属性,而不复制它的功能:

function student(id, name, marks, mob, home){
    this.id = id;
    this.name = name;
    this.marks = marks;
    this.contacts = {};
    this.contacts.mob = mob;
    this.contacts.home = home;

    this.toContactDetailsString = function(){
        return this.name +':'+ this.mob +', '+ this.home
    }

    // Copy the object to baseCopy 
    this.baseCopy = clone(this); // "clone" `this.baseCopy`
}

function clone(obj){
    if(obj == null || typeof(obj) != 'object'){ // If the current parameter is not a object (So has no properties), return it;
        return obj;
    }

    var temp = {};
    for(var key in obj){ // Loop through all properties on a object
        if(obj.hasOwnProperty(key) && !(obj[key]  instanceof Function)){ // Object.prototype fallback. Also, don't copy the property if it's a function.
            temp[key] = clone(obj[key]);
        }
    }
    return temp;
}

var s = new student(1, 'Jack', [5,7], 1234567890, 0987654321);
s.marks = s.marks.concat([6,8]); // Jack's gotten 2 new marks.

console.log(s.name + "'s marks were: ", s.baseCopy.marks);
// Jack's marks were:  [5, 7]
console.log(s.name + "'s marks are: ", s.marks);
// Jack's marks are:  [5, 7, 6, 8]
console.log(s.baseCopy.toContactDetailsString); // check if the function was copied.
// undefined
console.log(s.baseCopy.contacts.mob);
// 1234567890

(我会在深拷贝上工作一秒钟)

“深”副本现在应该可以工作了。

于 2012-12-20T09:53:35.627 回答
1
this.baseCopy = new student(id, name, marks);

你的方式只是做一个循环引用。用于new实例化一个新对象。

不过,使用它可能会陷入无限递归。

您可以像这样规避这种情况:

function student(id, name, marks, flag) {
    // usual code...
    // And:
    if (!flag) {
        this.baseCopy = new student(id, name, marks, true);
    }
}

这样,只有优等生有一个baseCopy。

于 2012-12-20T09:46:38.930 回答
1

出色地...

this.baseCopy = this;

基本上意味着对象的 baseCopy 就是对象本身。所以:

var abc = new student(someId, someName, someMarks);

abc 和 abc.baseCopy 实际上指向同一个对象。您可以做的可能是将 baseCopy 更改为:

this.baseCopy = { id: id, name: name, marks: marks, contact: {mob:mob, home: home}}

基本上手动将输入的副本创建到对象中。请注意,如果任何输入是引用类型,则副本仍将指向与原始对象相同的对象。

于 2012-12-20T09:48:17.760 回答