2011-02-03 5 views
3

У меня есть массив JavaScript внутри пространства имен, как это:Передать массив JavaScript в локальную переменную по ссылке?

app.collec.box = []; 

и у меня есть функция внутри того же пространства имен, как это:

app.init = function() { 
    var box = this.collec.box; 
    // ... code to modify box 
}; 

Я думал, что установка локальной переменной, равной объекта или свойство объекта было просто ссылкой на оригинал, но, похоже, я ошибаюсь, после изменения содержимого локальной переменной box внутри моей функции app.collec.box не изменяется.

Помогите, что я делаю неправильно? как я могу это решить?

Заранее спасибо.

EDIT. Это полный код.

var app = { 
    collec: { 
     box: [], 
     cache: [] 
    }, 

    init: function() { 
     var box = this.collec.box; 

     $.ajax({ 
      url: 'file.json', 
      success: function (json) { 
       // Map JSON array to box array using Underscore.js _()map 
       box = _(json).map(function (o) { 
        return new Model(o); 
       }); 
      } 
     }); 
    } 
}; 

app.init(); 
+3

Вы исключили соответствующий код из своего вопроса. – user113716

+0

@patrick действительно. @VerizonW, пожалуйста, включите фрагмент кода, который фактически вызывает вызов app.init. –

+0

Вы должны изучить геттеры и сеттеры: http://stackoverflow.com/questions/812961/javascript-getters-and-setters-for-dummies –

ответ

6

Ссылки указывают на объекты, а не на переменные. box не является ссылкой на переменную this.collec.box; скорее, box и this.collec.box являются ссылками на один конкретный объект в памяти. Вы можете изменить свойства этого объекта с помощью любой из этих переменных, но вы не можете использовать одну переменную для изменения другой переменной.

Если вы хотите изменить то, что this.collec.box относится, вам необходимо либо установить его непосредственно, как это:

this.collec.box = ...; 

или использовать ссылку на this.collec объекта и изменить его box свойство:

var x = this.collec; 
x.box = ...; 

Редактировать: Возможно, несколько диаграмм упростит понимание того, что h appening.

При назначении box = this.collec.box, это то, что происходит на самом деле:

this.collec.box -----> (object) <----- box 

Обе переменные указывают на тот же объект в памяти, но ни в коем случае не может box на самом деле относятся к переменной this.collec.box.

Что вы ожидали бы работать, если это произошло:

box -----> this.collec.box -----> (object) 

, но этого не происходит.

+0

Этот ответ содержит неверную информацию. Код, указанный выше, будет работать, как ожидает OP, * if * app.init вызывается таким образом, что 'this' фактически ссылается на' app.init' (например, просто вызывает 'app.init()'. –

+0

@Jason: Что вы говорите? Ясно, что этот ответ предвосхищает «это», ссылаясь на «приложение». OP не показывал *, что * он делает с 'box'. – user113716

+0

@ Джейсон ЛеБрун: Насколько я понимаю, OP пытается сделать 'box = ...' внутри функции и спрашивает, почему это изменение не отражается в 'this.collec.box'. – casablanca

0

Вы можете попробовать использовать

app.init = function (box) { 
    // ... code to modify box 
}; 

app.init(this.collec.box); 
+2

Каково значение 'this', которое вы используете в аргументе, отправленном' init'? – user113716

3

Что вы делаете, должны работать.

Я думаю, что ваша проблема связана с ключевым словом (хотя я не могу быть уверен, не видя больше вашего кода). этот, скорее всего, относится к самой функции (app.init), а не приложение.

Для устранения попробуйте изменить ...

вар коробка = this.collec.box;

... до ...

вар коробка = app.collec.box;

[EDIT]

После видеть больше кода, мой ответ до сих пор стоит: просто заменить это с приложение.

Вы также должны поместить эту строку (var box = app.collec.box;) внутри функции обратного вызова. Я не думаю, что обратный вызов сохранит ссылку на поле, так как это асинхронный вызов.

+0

Это не поможет в этом случае, ответ Касабланки - тот, который нужен OP. –

+0

Спасибо, но сменив его на app.collec.box, не удалось решить проблему – VerizonW

+0

Не стоит беспокоиться. Рад, что ты это понял. – RunnerRick

0

Возможно, вы передаете приложение app.init таким образом, что контекст приложения теряется. Когда вы делаете что-то вроде div.onclick = app.init или SetTimeout (app.init, 1000), когда app.init наконец получает перезвонил, this будет не пункт app, он будет указывать на div или window соответственно.

Если вам нужно назначить метод объекта в качестве обратного вызова, используйте закрытие. Например:

div.onclick = function() { app.init() };

0

только догадка:

Вы можете использовать один из методов экземпляра массива, которые возвращают новый экземпляр массива вместо изменения исходного массива. Вы случайно используете либо concat, join, либо slice? Это аксессоры, а не мутаторы.

также:

Если вы изменяете локальную переменную box, убедитесь, что вы назначаете его обратно, когда вы сделали:

var box = this.collec.box; 
// ... code to modify box 
this.collec.box = box; 
1

поскольку браузер лексической области видимости, то this ключевым слова будет ссылаясь на анонимную функцию вместо фактического ключевого слова app, как то, что говорит @rick roth. вы должны сделать закрытие и иметь что-то вроде этого за пределами Вашей анонимной функции:

var ns = this; 

и тогда вы могли бы сделать

ns.collec.box = []; 

ns может быть все, что вы хотите, но затем в течение app.init, вы бы ссылки массив так:

app.init = function() { 
    var box = ns.collec.box; 
    // ... code to modify box 
}; 

так, то, до тех пор, как ваша крышка установлена ​​правильно, все, что указывает на ns, будут правильно указаны.

Смежные вопросы