JavaScript: сохранить несколько экземпляров объектов JavaScript от удаления после завершения? - PullRequest
1 голос
/ 13 января 2012

У меня есть следующий код:

$(document).ready(function() {

    $('.container').ready(function() {

        var v = new Video($(this));
        v.load();

    });

});

Как я могу удержать v от утилизации?Инициализированный класс загружает 3 переменные: video, source и controls.Когда слушатель щелчка или события вызывает свою функцию и пытается получить доступ к любому из них, он не может этого сделать, поскольку с тех пор он был уничтожен.

Как обойти эту проблему?

Еще пример кода:

$.Class('Video', {
    init: function(container) {
        this.video = container.find('.video');
        this.source = this.video[0];
        this.controls = {
            // ...
            total: container.find('.total'),
            buffered: container.find('.buffered')
        };
    },
    load: function() {
        this.source.addEventListener('progress', function() {
            var buffered = Math.floor(this.source.buffered.end(0)) / Math.floor(this.source.duration);
            this.controls.buffered.width(Math.floor(buffered * this.controls.total.width()));
        }, false);
    }
});

Ответы [ 6 ]

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

Вы должны держать ссылки вокруг.Вы должны иметь пространство имен приложения и хранить в нем объект модели.

window.App = {}; // global object literal acting as a cache lookup

App[video.id] = video; // store the object when its created.

Если вы сделаете это, вы всегда можете искать объекты по идентификатору (или некоторому другому идентифицирующему параметру).Если вам нужно только сохранить этот один объект, просто поместите его в глобальную область, удалив var из его объявления.

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

Переменные в JavaScript являются областью действия функции, поэтому, когда функция обратного вызова, переданная в $ ('. Container'). Ready (), завершается, переменная, которую вы объявили в этой функции, v, выходит за пределы области видимости и может быть очищена коллекция.

Один из способов избежать этого - объявить глобальную переменную и сохранить в ней ваш объект Video. Например:

var v;  // Global, because it is declared outside any function
$(document).ready(function() {
    $('.container').ready(function() {
        v = new Video($(this));
        v.load();
    });
});

Конечно, глобальные переменные, по крайней мере, доставляют столько же проблем в JavaScript, как и в любом другом языке (может быть, даже больше). Рекомендуется объявлять ровно одну глобальную переменную, объект, для всей вашей страницы / приложения и хранить все и все ваши постоянные данные в этом объекте. Вы хотите дать этому одиночному глобальному имени имя, которое, вероятно, будет уникальным, чтобы оно не конфликтовало с какими-либо сторонними сценариями, которые вы можете использовать. Мне нравится использовать соглашение, используемое с пространствами имен Java для использования зарегистрированного доменного имени, связанного с работой, в качестве уникального идентификатора. Так что если вы или ваш работодатель владеете доменным именем examplename.com:

if (! window.examplename) {
    window.examplename = {};
}
examplename.videos = [];

...

$(document).ready(function() {
    $('.container').ready(function() {
        var v = new Video($(this));
        v.load();
        examplename.videos.push(v);
    });
});

В другом месте в вашем коде доступ к видеообъектам выглядит так:

$.each(examplename.videos, function(idx, vid) {
        vid.someMethod();
    });
1 голос
/ 13 января 2012

Я бы использовал функцию jQuery .data и сохранил бы их в .container.

$(this).data('video', new Video($(this));

Чтобы читать, вы можете использовать, как показано ниже, из любого места

$('.container').data('video');

Редактировать: Можете ли вы попробовать изменить код, как показано ниже,

$.Class('Video', {
    init: function(container) {
        var video = container.find('.video');
        var source = this.video[0];
        var controls = {
            // ...
            total: container.find('.total'),
            buffered: container.find('.buffered')
        };

        //added code
        container.data('player_props', {'video': video, 'source': source, 'controls': controls});

    },
    load: function() {
        this.source.addEventListener('progress', function() {
            //added code
            var playerProps = $('.container').data('player_props'); 

            //modified referneces of source and control
            var buffered = Math.floor(playerProps['source'].buffered.end(0)) / Math.floor(playerProps['source'].duration);
            this.controls.buffered.width(Math.floor(buffered * playerProps['controls'].total.width()));
        }, false);
    }
});
0 голосов
/ 13 января 2012

Область видимости переменной javascript связана с функцией, в которой она объявлена ​​(т. Е. Где var. Если нет var, то она находится в глобальной области видимости.

Так что вопросна самом деле не в том, как остановить его удаление, а в том, как вы можете обеспечить его доступность там, где вы хотите.

Если вы хотите, чтобы он был доступен абсолютно везде (подсказка: вы, вероятно, этого не делаете, глобальные переменныев javascript это распространенный источник ошибок), тогда просто удалите var.

. Если вы хотите, чтобы он был доступен для остальной части функции, вызываемой $(document).ready, тогда перемещайте var v, таким образом,добьется цели.

$(document).ready(function() {
    var v;
    $('.container').ready(function() {

        v = new Video($(this));
        v.load();

    });

});

Обычный метод - использование анонимной функции для создания более широкой области видимости для любых переменных, которые вы хотите сделать доступными из нескольких функций, не делая их полностью глобальными, таким образом:

(function(){
     var v, f0, f1;

     f0 = function (){
       v = 1;
     };

     f1 = function (){
       v += 1;
     };
}());
0 голосов
/ 13 января 2012

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

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

Использование var объявляет переменную как локальную.Брось это, и с тобой все будет в порядке ...

v = new Video($(this));
...