0

I really never used a javascript function type or class before, I understand Java and Python, but not javascript. So, I build a class like this:

function FormStore (type) {

    this.setup = () =>{
        this.store = {};
        this.ERR_LINE_PREFIX = '#err_';
        this.NO_DISPLAY_CLASS = 'no-display';
        this.settings = {
            'myID':{'hide':false},
        }
    }

    this.checkVal= () => {
        var geoArr = ['id_xx','myID', (...)];
        var id;
        $.each( geoArr, function(val) {
            id = geoArr[val];
            console.log(this.store) //-> returns undefined, below line is error
            if (!(this.store[id])) { 
                return false;
            }

        });
};

var FS = new FormStore();
FS.setup();

The store is filled by components on document.ready. There is a function that looks up if the aligned components (glyph, label, input) have some classes or values and for the specific component fills a dict: {label:false,glyph:false, input:false}. However, for some reason it doesn't matter. Even if I enter some values in to the store right away (in setup) or create them on the fly, in checkVal the store doesn't exist, it's undefined.

Please, anybody, what am I not understanding about javascript type and classes here? I am googling this a lot and trying to find good resources but, "javascipt variable class" (or type) just yields a lot of DOM manipulation.

3 Answers 3

1

edit

There is a context problem in checkVal, you are using a non-arrow (and not explicitly bound) callback function and trying to access this inside of it. Change that to an arrow function as well, and the parent context (this) will be preserved:

$.each( geoArr, (val) => {
    id = geoArr[val];
    console.log(this.store)
    if (!(this.store[id])) { 
        return false;
    }
});

And while you are at changing that section, it's not going to work. You will not get access to $.each's return value. You should rely on native array APIs for this task and use Array.every to determine if all geoArr items are in the store (assuming that's your goal):

// returns false if not all geoArr items are in the store
geoArr.every(id => this.store[id])

original

I don't see you calling checkVal() anywhere, but based on the error you are getting it is called prior to setup() (since setup initializes the store). You could solve that problem straight away by moving this.store = {} out of setup (right at the top), e.g.:

function FormStore(type) {
   this.store = {};
   ...

Having said that, I would suggest either defining your methods on the prototype, or utilizing ES6 classes. Here is a simplified version of both:

ES5 class

function FormStore(type) {
   // make sure user didn't forget new keyword
   if (this === window) { 
      throw new Error('FormStore must be called with "new" keyword')
   }
   // initialize state, this is the constructor
   this.type = type;
   this.store = {};
   // any other state the class manages
}

FormStore.prototype = {
   setup: function() {
      // do setup stuff
      // "this" points to instance
      console.log('setup', this.type)
   },
   checkVal: function() {

   }
}

var formStore = new FormStore('foo')
console.log(formStore.store) // <-- not undefined
formStore.setup()

ES6 Class

class FormStore {
   constructor(type) {
      this.type = type;
      this.store = {};
   }
   setup() {
      console.log('setup', this.type)
   }
   checkVal() {

   }
}

const formStore = new FormStore('bar')
console.log(formStore.store) // <-- not undefined
formStore.setup()

Sign up to request clarification or add additional context in comments.

2 Comments

The store is initialized and setup is called in the next line (see bottom of my snnipet), there is no way checkVal would be called sooner as setup. It's true that the snippet doesn't show the use of checkVal, but I just thought it's unimportant because it shows FormStore initialization and Fs.setup(). I tried to move the sotre definition out of the setup, it didn't matter. Thanks for the class proposals, i will try them.
Please see my later updates, I saw after I posted that you were switching contexts in your callback inside checkVal. I left my other code up to hopefully help with the OOP JS :)
1

It has to do with scoping. Your $.each in checkVal has a normal function. Inside the function the scope if this is different. If you want to keep the original scope you could use a fat arrow function like you do when defining the methods.

this.checkVal= () => {
    var geoArr = ['id_xx','myID', (...)];
    var id;
    $.each( geoArr, val => {
        id = geoArr[val];
        console.log(this.store) //-> returns undefined, below line is error
        if (!(this.store[id])) { 
            return false;
        }
    });
}

When you run your original code and place a breakpoint on the line with console.log you can see in the inspector that this is set to the Window object and no longer points to your FormStore.

1 Comment

Thanks, you are correct. However I marked Rob M. answer as accepted because he also identified the issue correctly and added usefull information about js classes.
0
function FormStore () {

    this.setup = function(){
        this.store = {};
        this.ERR_LINE_PREFIX = '#err_';
        this.NO_DISPLAY_CLASS = 'no-display';
        this.settings = {
            'myID':{'hide':false},
        }
    }

    this.checkVal= function(){
        var geoArr = ['id_xx','myID'];
        var id;
        $.each( geoArr, function(val) {
            id = geoArr[val];
            console.log(this.store) //-> returns undefined, below line is error
            if (!(this.store[id])) { 
                return false;
            }

        });
    }
};
var FS = new FormStore();
FS.setup();

Works absolutely fine, the code you provided had a missing bracket and you were using some broken es6 syntax

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.