Является ли расширение jQuery созданием ссылки между объектами? - PullRequest
4 голосов
/ 13 января 2012

Я расширяю дерьмо выстрелом. После расширения почему модификация Shot Alter Shat?

var shat = [{bang:true}, {bumm: false}, {bong: false}]
var shot = [{bang:false}, {bumm: false}, {bong: false}]

$.extend(shat, shot)

shot[0].bang = true

console.log("shat", shat) 
// prints
Object
bang: true // why is this true?
Object
bumm: false
Object
bong: false

Я предполагаю, что ссылка создана или расширение по какой-то причине происходит после снимка [0] .bang = true. Проблема в том, что я хочу изменить снимок после расширения, но, конечно, не хочу, чтобы это влияло на шат. Есть идеи, почему это происходит и что я могу сделать, чтобы избежать этого?

см. JSfiddle testcase: http://jsfiddle.net/yEnph/3/

Ответы [ 4 ]

5 голосов
/ 13 января 2012

По умолчанию $.extend свойства только поверхностных копий *.Это не очень интересно.

В этом случае расширенными свойствами являются "0", "1", "2" и т. Д., И, таким образом, shat[0] === shot[0] имеет значение true после расширения , что только , в случае, если оба оценивают один и тот же объект.Так как они - один и тот же объект, тогда ... ну, мутируя его в одном месте, мутирует его везде .

Чтобы разделить их, рассмотрим "глубокую копию" (см. Различные способы вызова)1017 * jQuery.extend ).Другой подход, о котором я упоминаю, поскольку он также может использоваться в других контекстах, заключается в сериализации объекта и последующей десериализации его - например, с помощью JSON.

var shat = [{bang:true}, {bumm: false}, {bong: false}]
var shot = [{bang:false}, {bumm: false}, {bong: false}]
$.extend(true, shat, shot) // use "deep copy"
shat[0] === shot[0]        // false; different objects now so...
shot[0].bang = "boom"      // ...this will not affect the object named by shat[0]
shot[0].bang               // "boom"
shat[0].bang               // false

Счастливое кодирование.


* То есть для каждого свойства, p в исходном объекте (ах), оно просто делает target[p] = source[p].Помните, что в JavaScript массивы - это просто особый подтип объекта с магическим значением length: значение в индексе n именуется свойством "n".

2 голосов
/ 13 января 2012

Из документа jQuery http://api.jquery.com/jQuery.extend/, похоже, что $ .extend только увеличивает объект, но не массив. В этом примере ваша переменная shat никогда не изменялась.

1 голос
/ 13 января 2012

Интересно, что это работает вообще, не знал, что extend работает с массивами.

Причина этого заключается в том, что оба массива содержат ссылку на один и тот же объект.По той же причине, что это предупредит "новый":

http://jsfiddle.net/yEnph/4/

var a = { test: "one"};
var b = a;

a.test="new";

alert(b.test);

Обе переменные имеют ссылку на один и тот же объект, поэтому редактирование объекта обновляет объект, который они обассылка. * * +1010

0 голосов
/ 13 января 2012

Расширение просто переписывает свойства, если ключи взяты:

var a = {
   hello: "kitty"
},

b = {
   hello: "world"
}

$.extend( a, b );

console.log( a );
//Object
//hello: "world"

Поскольку массивы - это просто объекты с числовыми именами свойств, вы замените их тем же принципом, за исключением того, что "hello" равно "0" и т. Д.

Поскольку у вас есть объекты вместо примитивов, shat получает объекты shot, они переписываются, поэтому исходные shat объекты теряются. Таким образом, изменение объектов shot приведет к изменению объектов shat, поскольку они являются одинаковыми объектами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...