"это" в массиве раскрытия прототипа

Хорошо, ребята, я бился головой об этом. Я чувствую, что это проблема "указателя" при использовании массива классов, созданного из шаблона выявления прототипа. Кроме того, я использую knockoutjs для своей привязки.

Проблема: у меня обычно есть очень вовлеченные страницы на моем сайте. В результате я склонен иметь классы, которые содержат массивы других классов. Я все время использую Revealing Prototype Pattern и обычно имею переменную "self", которая указывается на "this" в функции init, так что другие функции в этом классе, вызываемые обработчиками событий, будут иметь указатель на this (и это не подводит - кажется, знает, что такое "я").

НО.... когда у меня есть массивы класса (модели), он не работает правильно.... мой класс MailModel (моя viewmodel) имеет массив классов People..."self" в классе People указывается на "это", но когда другие функции прототипа вызывают "себя", это, кажется, указывает на последний элемент "персона" в массиве?? - Я как-то выставляю "я" как разделяемую функцию на всех классах, которые он создает… и как-то указываю на этот последний экземпляр "этого"??

Я попытался сделать простой макет viewModel, содержащий массив классов "Person". ПОЖАЛУЙСТА, кто-нибудь, помогите мне разобраться в этом. Я пробовал разные способы использования этого указателя this в классе Person, но безрезультатно.

Проверьте это!

http://jsfiddle.net/N8vxr/.

var $results = $('#results');

var Person = function(data) {
  this.id = ko.observable();
  this.name = ko.observable();
  this.init(data);
}

Person.prototype = function(){
    var self,
        init = function(data){
            self = this;

            self.id(data.id || 0)
                .name(data.name)

        },
       sayHi = function(){
            $results.find('.wrong').text(self.name()).end()
                    .find('.correct').text(this.name()).end()
                    .show();
        };
    return {
        init: init,
        sayHi: sayHi
    }
}();

var MainModel = function(people){
    this.people = ko.observableArray([]);
    this.init(people);
}

MainModel.prototype = function(){
    var self,
        init = function(people){
            self = this;

            _.each(people, function(person){
                self.people.push(new Person(person));
            }); 

            /* do lots of other stuff */
        };
    return {
        init: init
    }
}();

var people = [
    {id: 1, name: 'Bill Smith'},
    {id: 2, name: 'John Doe'},
    {id: 3, name: 'Suzy Chapstick'},
];

var vm = new MainModel(people);

 ko.applyBindings(vm);
ОБНОВИТЬ:

Я вижу комментарий, задающийся вопросом, почему я не просто использовал бы "this" в своем вызове - в моем случае у меня есть другие вещи, вызывающие эти функции-прототипы, которые НЕ являются экземпляром person (так что "this" не работает) - я обновил мой jsFiddle, чтобы показать прототип Person с вычисляемой функцией totalNums KnockoutJS для итогов - если я добавлю "this" в эту функцию, произойдет сбой, так как "this" является объектом "Window" - и, как и раньше, вы можете увидеть это, используя "self" "просто относится к последнему человеку в массиве (обратите внимание, что у всех"totalNums"равно 80 (Suzy Chapstic)

Если я перенесу этот "totalNums" в конструктор, это нормально, но я хочу, чтобы мои функции были в прототипе. Итак... как я могу получить ссылку на этот экземпляр внутри этой вычисляемой функции в прототипе?

Вот обновленная скрипка с этой вычисляемой функцией KnockoutJS:

http://jsfiddle.net/Sj25M/

1 ответ

Решение

self действительно переменная замыкания Person.prototype.init и, следовательно, он является общим для всех случаев; это один экземпляр меняет его, все остальные видят изменения. Это способ закрытия работы; то, что "захватывается" замыканием, является ссылкой на переменную, а не на значение переменной во время создания экземпляра.

Я не уверен, зачем вам это нужно в первую очередь: когда бы ни Person.prototype называется, this будет указывать на правильный экземпляр. Если одному из методов нужно вызвать анонимную функцию, которой нужен экземпляр в качестве закрывающей переменной, он может создать локальную переменную var self=this и использовать это.

Другие вопросы по тегам