Question

OK guys - been banging my head on this one. I feel this is a "pointer" issue while using an array of classes built from the Revealing Prototype Pattern. Also, I'm using knockoutjs for my binding.

Issue: I commonly have very involved pages on my site. As a result, I tend to have classes that contain arrays of other classes. I use the Revealing Prototype Pattern all the time and usually have a "self" variable that gets pointed to "this" in the init function so that other functions in that class that are called by event handlers will have a pointer to this (and it doesn't fail - it seems to know what "self" is).

BUT....when I have arrays of a class(model) it doesn't work correctly....my MailModel class (my viewmodel) has an array of People classes..."self" in the People class gets pointed to "this", but when other functions of the prototype call "self", it seems to be pointing to the LAST "person" item in the array?? - Am I somehow exposing "self" as a shared function on all the classes it instantiates....and somehow pointing to that last instance of "this"??

I tried to do a simple mock-up of a viewModel containing an array of "Person" classes. PLEASE someone help me figure this out. I've tried different ways of using this "this" pointer on the "Person" class, but to no avail.

Check it out!

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);
UPDATE:

I see the comment wondering why I would not just use "this" in my call - In my case, I have other things calling these prototype functions that are NOT the person instance (so "this" doesn't work) - I have updated my jsFiddle to show the Person prototype with a totalNums KnockoutJS computed function for totals - if I put "this" in that function, it fails since "this" is the "Window" object - and as before, you can see that using "self" just refers to the last person in the array (notice everyones "totalNums" is 80 (Suzy Chapstic)

If I move that "totalNums" up into the constructor, it is fine, but I want my functions down in the prototype. So......how can I get a reference to the "this" instance inside of that computed function on the prototype?

Here is the updated fiddle with this KnockoutJS computed function:

http://jsfiddle.net/Sj25M/

Was it helpful?

Solution

self is indeed a closure variable of Person.prototype.init and consequently it's shared by all instances; it one instance changes it, all the others see the change. That's the way closures work; what gets "trapped" by a closure is a reference to the variable, not the value of the variable at the time of instantiation.

I'm not sure why you need it in the first place: whenever any method in Person.prototype is called, this will be pointing to the correct instance. If one of the methods needs to invoke an anonymous function that needs the instance as a closure variable, it can create a local variable var self=this and use it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top