2

As for a JS-newbie, I'm struggling with JS-closure. Googled enough, though can't understand why "this" is not available in "store" function. Any help will be appreciated:

;(function (win) {
var _af = function(storeObjectName, storeObjectValue) {
    var self;
    if (_af.prototype.instance) {
        self = _af.prototype.instance;
    } else {
        self = Object.create(_af.prototype);
        _af.prototype.instance = self;
        self._init();
    }
    if (arguments.length == 1) return self.fire(storeObjectName);
    if (arguments.length == 2) self.store(storeObjectName, storeObjectValue);
    return self;
};

_af.prototype = {
    afVariable: '_af',
    afObject: {},

    _init : function(){
        this.afObject = this.get(self.afVariable);
    },

    store : (storeObjectName, storeObjectValue)=>{
        // This throws the error, that this.get is not defined
        this.get('_af');
    },

    get : storageObject=>{
        if (!storageObject)
            this.afObject = '_af';
        else
            this.afObject = '_someother'
    }
}
win._af = _af;
}(window));
SmileCold
  • 21
  • 1
  • how do you create `_af`? – Max Koretskyi Jan 05 '17 at 14:17
  • What is your test? Are you calling `new _af` and then running `.store()`? Or are you just trying `_af.store()`? – somethinghere Jan 05 '17 at 14:22
  • Related [Arrow function vs function declaration / expressions: Are they equivalent / exchangeable?](http://stackoverflow.com/questions/34361379/arrow-function-vs-function-declaration-expressions-are-they-equivalent-exch) – Felix Kling Jan 05 '17 at 14:27

1 Answers1

2

It's because you use a lambda expression ((...) => ...) instead of function() { ....

In JS this depends a lot on the context. In your case, since the prototype is an object, whenever you want to use this to refer to that object, you must do it in a function defined in the object like:

store : function(storeObjectName, storeObjectValue) {
    // This throws the error, that this.get is not defined
    this.get('_af');
},

or (also correct):

store(storeObjectName, storeObjectValue) {
    // This throws the error, that this.get is not defined
    this.get('_af');
},

Note you are doing it correctly for _init, but not for store and get

When you use the lambda syntax, this will refer to the current this, when a function is created, so it will be window.

Also avoid using get as a function / or any other name because it is used for defining getters.

Ovidiu Dolha
  • 5,335
  • 1
  • 21
  • 30
  • 2
    that's correct, the only thing is that _When you use the lambda syntax, this will refer to the outer object (in this case function (win))_ - it will refer to the current `this`, when a function is created, so it will be `window`, not `function (win)` – Max Koretskyi Jan 05 '17 at 14:26
  • FWIW, the official term is "arrow function". Also, `get` is not a keyword. – Felix Kling Jan 05 '17 at 14:27
  • Thanks, changing the lambda expression to regular function worked. – SmileCold Jan 05 '17 at 17:38