Передать массив JavaScript в локальную переменную по ссылке? - PullRequest
3 голосов
/ 03 февраля 2011

У меня есть массив JavaScript внутри пространства имен, как это:

app.collec.box = [];

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

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

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

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

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

РЕДАКТИРОВАТЬ. Это полный код.

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();

Ответы [ 6 ]

6 голосов
/ 03 февраля 2011

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

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

this.collec.box = ...;

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

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

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

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

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

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

То, что вы ожидаете, сработает, если это произойдет:

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

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

3 голосов
/ 03 февраля 2011

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

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

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

var box = this.collec.box;

... на ...

var box =app.collec.box;

[РЕДАКТИРОВАТЬ]

После просмотра большей части кода мой ответ остается в силе: просто замените этот на app .

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

1 голос
/ 03 февраля 2011

, поскольку javascript ограничен лексической областью, ключевое слово 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, будет правильно ссылаться.

0 голосов
/ 03 февраля 2011

Просто догадка:

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

Также:

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

var box = this.collec.box;
// ... code to modify box
this.collec.box = box;
0 голосов
/ 03 февраля 2011

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

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

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

0 голосов
/ 03 февраля 2011

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

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

app.init(this.collec.box);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...