0

I have two objects defined, each one has an init function as follows

var TestSound = {
    settings: {
        testSoundFile : "static/main/persoonS",
        postUrl : "dummy.com",
    },
    init : function(){
        this.cacheDom();
         this.bindEvents();
    },
    cacheDom: function(){
        this.oneCertainButton = document.getElementById("buttonId");
        this.soundElement = document.getElementById("sound");
    },
    bindEvents : function(){
        that = this;
        this.oneCertainButton.onclick = function(){ that.playSound(that.settings.testSoundFile); };
    },
    ............

var CheckInput = {
   settings: {
    correctAnswer : "persoon",
   },
   init : function (){
       this.cacheDom();
       this.bindEvents();
   },
   cacheDom: function (){
       this.submitButton = document.getElementById("submitButtonId");
       this.answerInputBox = document.getElementById("answerId");
       this.feedbackField = document.getElementById("feedbackId");
   },
   bindEvents: function(){
       that = this;
       this.submitButton.addEventListener("click",  function(event){
  ..........

I wish to initialise them both (one after the other) with "window onload" like so:

window.onload = function() { 
   CheckInput.init.bind(CheckInput);
   TestSound.init.bind(TestSound);
};

This doesn't work apparently as the init functions do not seem to be called.

However, it works if I initialise just one of the modules like so:

window.onload =
   CheckInput.init.bind(CheckInput);

Any explanations on what is going wrong here much appreciated!

DeBaze
  • 383
  • 1
  • 15
  • 2
    [Function.prototype.bind](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind) does not call a function. – ASDFGerte Oct 12 '16 at 14:17
  • Sure but it should be called when window.onload fires. – DeBaze Oct 12 '16 at 14:18

1 Answers1

1

You want either

window.onload = function() { 
    CheckInput.init();
    TestSound.init();
};

or

window.addEventListener("load", CheckInput.init.bind(CheckInput));
window.addEventListener("load", TestSound.init.bind(TestSound));

Any explanations on what is going wrong here much appreciated!

You have to create a function to be used as a handler that is called when the event fires. You can do that by using bind or with a function expression, but if you use both then only another function will be created when the event happens, and the init method is not called at all.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • @DeBaze Which one? What "doesn't work"? Do you get an error? What does the debugger say? – Bergi Oct 12 '16 at 14:57
  • Well the 'this' in 'Check Input' still refers to the TestSound Object, that is in the 'bindEvents' function. However by logging 'this' (via JSON.Stringify) in the console from the 'init' function, it seems to correctly refer to 'Check Input'. I'm probably making a stupid mistake here, but cant put my finger on it – DeBaze Oct 12 '16 at 14:59
  • Note: I used the second option from the answer – DeBaze Oct 12 '16 at 15:00
  • 1
    @DeBaze Ah, the `that` in `bindEvents`… Yeah, that doesn't work, because it's [implicitly global](http://blog.niftysnippets.org/2008/03/horror-of-implicit-globals.html) and contains the last value assigned to it. Make it two local variables by prefixing them with `var`. I also would recommend strict mode. – Bergi Oct 12 '16 at 15:03
  • Notice that you also could use `this.oneCertainButton.onclick = this.playSound.bind(this, this.settings.testSoundFile);` (however evaluating the settings immediately instead of on every event) or `this.oneCertainButton.onclick = function(){ TestSound.playSound(TestSound.settings.testSoundFile); };` (without `that`), given it's a singleton - see [here](http://stackoverflow.com/a/10711164/1048572) for details – Bergi Oct 12 '16 at 15:09
  • Thanks for pointing me to it. Now I understand fully where the error comes from. I knew about implicit globals, but didn't think it as a danger here because I supposed vars in the object's scope are local to the object. I suppose that is still the case with objects (like "settings" which are present in both TestSound and CheckInput). Just didn't realise the 'thats' in both are global. Thanks a lot for making that clear. – DeBaze Oct 12 '16 at 15:11
  • You're last comment I still need to study on it. Also, I think I can initialise both as follows: ``` window.onload = function() { CheckInput.init.bind(CheckInput)(); TestSound.init.bind(TestSound)(); } – DeBaze Oct 12 '16 at 15:13
  • 1
    Regarding `settings`, that's different from `that` because it's a property not a variable. Yes, `CheckInput.init.bind(CheckInput)();` does in theory work but in practice is bad style - it's equivalent to `CheckInput.init.calll(CheckInput)` or just `CheckInput.init()` and you should prefer the shorter (and more efficient) one. – Bergi Oct 12 '16 at 15:16
  • Ok I understand. Problem started when I wanted to unnecessary bind the objects as 'this' in the init calls, not realising my problems were caused by the global 'that'. Everything is a lot clearer now, thanks again for all your help! – DeBaze Oct 12 '16 at 15:22