Я изменил примеры, чтобы лучше продемонстрировать, что здесь происходит.Demo
Сначала мы создаем объект с тремя свойствами; Число, строка и объект с одним свойством со строковым значением.
Затем мы создаем второй объект из первого, используя Object.create()
;
var obj1 = {
num : 1,
str : 'foo',
obj : { less: 'more' }
};
var obj2 = Object.create(obj1);
console.log('[1] obj1:', obj1);
console.log('[1] obj2:', obj2);
"[1] obj1:"
[object Object] {
num: 1,
obj: [object Object] {
less: "more"
},
str: "foo"
}
"[1] obj2:"
[object Object] {
num: 1,
obj: [object Object] {
less: "more"
},
str: "foo"
}
Выглядит хорошо, верно? У нас есть наш первый объект и второй скопированный объект.
Не так быстро; Посмотрим, что произойдет, когда мы изменим некоторые значения для первого объекта.
obj1.num = 3;
obj1.str = 'bar';
obj1.obj.less = 'less';
console.log('[2] obj1:', obj1);
console.log('[2] obj2:', obj2);
"[2] obj1:"
[object Object] {
num: 3,
obj: [object Object] {
less: "less"
},
str: "bar"
}
"[2] obj2:"
[object Object] {
num: 3,
obj: [object Object] {
less: "less"
},
str: "bar"
}
Теперь снова наш первый объект, с изменениями, и копия этого объекта. Что тут происходит?
Давайте проверим, имеют ли объекты свои свойства.
for(var prop in obj1) console.log('[3] obj1.hasOwnProperty(' + prop + '): ' + obj1.hasOwnProperty(prop));
for(var prop in obj2) console.log('[3] obj2.hasOwnProperty(' + prop + '): ' + obj2.hasOwnProperty(prop));
"[3] obj1.hasOwnProperty(num): true"
"[3] obj1.hasOwnProperty(str): true"
"[3] obj1.hasOwnProperty(obj): true"
"[3] obj2.hasOwnProperty(num): false"
"[3] obj2.hasOwnProperty(str): false"
"[3] obj2.hasOwnProperty(obj): false"
obj1
обладает всеми своими свойствами, так же, как мы определили, но obj2
не делает.
Что происходит, когда мы меняем некоторые свойства obj2
?
obj2.num = 1;
obj2.str = 'baz';
obj2.obj.less = 'more';
console.log('[4] obj1:', obj1);
console.log('[4] obj2:', obj2);
for(var prop in obj1) console.log('[4] obj1.hasOwnProperty(' + prop + '): ' + obj1.hasOwnProperty(prop));
for(var prop in obj2) console.log('[4] obj2.hasOwnProperty(' + prop + '): ' + obj2.hasOwnProperty(prop));
"[4] obj1:"
[object Object] {
num: 3,
obj: [object Object] {
less: "more"
},
str: "bar"
}
"[4] obj2:"
[object Object] {
num: 1,
obj: [object Object] {
less: "more"
},
str: "baz"
}
"[4] obj1.hasOwnProperty(num): true"
"[4] obj1.hasOwnProperty(str): true"
"[4] obj1.hasOwnProperty(obj): true"
"[4] obj2.hasOwnProperty(num): true"
"[4] obj2.hasOwnProperty(str): true"
"[4] obj2.hasOwnProperty(obj): false"
Так, num
и str
изменился на obj2
, а не на obj1
так же, как мы хотели, но obj1.obj.less
изменилось, когда он не должен иметь.
Из проверки hasOwnProperty()
мы можем видеть, что, хотя мы изменили obj2.obj.less
, мы не задали obj2.obj
. Это означает, что мы все еще имеем в виду obj1.obj.less
.
Создайте объект с obj1.obj
и назначьте его obj2.obj
и посмотрите, дает ли это нам то, что мы ищем.
obj2.obj = Object.create(obj1.obj);
console.log('[5] obj1:', obj1);
console.log('[5] obj2:', obj2);
for(var prop in obj1) console.log('[5] obj1.hasOwnProperty(' + prop + '): ' + obj1.hasOwnProperty(prop));
for(var prop in obj2) console.log('[5] obj2.hasOwnProperty(' + prop + '): ' + obj2.hasOwnProperty(prop));
"[5] obj1:"
[object Object] {
num: 3,
obj: [object Object] {
less: "more"
},
str: "bar"
}
"[5] obj2:"
[object Object] {
num: 1,
obj: [object Object] {
less: "more"
},
str: "baz"
}
"[5] obj1.hasOwnProperty(num): true"
"[5] obj1.hasOwnProperty(str): true"
"[5] obj1.hasOwnProperty(obj): true"
"[5] obj2.hasOwnProperty(num): true"
"[5] obj2.hasOwnProperty(str): true"
"[5] obj2.hasOwnProperty(obj): true"
Это хорошо, теперь obj2
имеет свою собственную obj
собственность. Посмотрим, что произойдет, когда мы изменим сейчас obj2.obj.less
.
obj2.obj.less = 'less';
console.log('[6] obj1:', obj1);
console.log('[6] obj2:', obj2);
"[6] obj1:"
[object Object] {
num: 3,
obj: [object Object] {
less: "more"
},
str: "bar"
}
"[6] obj2:"
[object Object] {
num: 1,
obj: [object Object] {
less: "less"
},
str: "baz"
}
Так что все это говорит нам о том, что, если имущество еще не было изменено на созданном объекте, любые get
запросы к созданному объекту для этого свойства будет перенаправлен к исходному объекту.
set
запроса obj2.obj.less = 'more'
от предыдущего кодового блока первым требует get
запроса на obj2.obj
, который не существует в obj2
в этой точке, так что он направляет к obj1.obj
и в своей очереди obj1.obj.less
.
потом, наконец, когда мы вновь читали obj2
, мы до сих пор не установлены obj2.obj
так что get
запроса будет направлен obj1.obj
и вернуть настройки, которые мы ранее изменились, вызывая эффект, изменяя свойства второго объекта возражать ребенок, похоже, меняет оба, но на самом деле это только изменение первого.
Вы можете использовать эту функцию, чтобы вернуть новый объект, полностью отделенный от оригинала рекурсивно.
Demo
var obj1 = {
num : 1,
str : 'foo',
obj : { less: 'more' }
};
var obj2 = separateObject(obj1);
function separateObject(obj1) {
var obj2 = Object.create(Object.getPrototypeOf(obj1));
for(var prop in obj1) {
if(typeof obj1[prop] === "object")
obj2[prop] = separateObject(obj1[prop]);
else
obj2[prop] = obj1[prop];
}
return obj2;
}
console.log('[1] obj1:', obj1);
console.log('[1] obj2:', obj2);
for(var prop in obj1) console.log('[1] obj1.hasOwnProperty(' + prop + '): ' + obj1.hasOwnProperty(prop));
for(var prop in obj2) console.log('[1] obj2.hasOwnProperty(' + prop + '): ' + obj2.hasOwnProperty(prop));
"[1] obj1:"
[object Object] {
num: 1,
obj: [object Object] {
less: "more"
},
str: "foo"
}
"[1] obj2:"
[object Object] {
num: 1,
obj: [object Object] {
less: "more"
},
str: "foo"
}
"[1] obj1.hasOwnProperty(num): true"
"[1] obj1.hasOwnProperty(str): true"
"[1] obj1.hasOwnProperty(obj): true"
"[1] obj2.hasOwnProperty(num): true"
"[1] obj2.hasOwnProperty(str): true"
"[1] obj2.hasOwnProperty(obj): true"
Давайте посмотрим, что происходит, когда мы изменили некоторые переменные в настоящее время.
obj1.num = 3;
obj1.str = 'bar';
obj1.obj.less = 'less';
console.log('[2] obj1:', obj1);
console.log('[2] obj2:', obj2);
"[2] obj1:"
[object Object] {
num: 3,
obj: [object Object] {
less: "less"
},
str: "bar"
}
"[2] obj2:"
[object Object] {
num: 1,
obj: [object Object] {
less: "more"
},
str: "foo"
}
Все работает именно так, как вы ожидали.
related: [JavaScript Object.create - наследование вложенных свойств] (http://stackoverflow.com/q/3191103/1048572) – Bergi