0

I have an object named Gallery with several properties and methods. One of them, setCurrentPicture, removes all existing photos and videos DOM elements from gallery container before showing new photo/video. Besides my gallery stops playing video (set this to pause mode) when the user clicks on it. This is togglePlayVideo method inside the Gallery prototype. First I remove elements from DOM and then showing new content. If this is video, I add eventListener to document, use bind method.

So, in the setCurrentPicture I want to remove EventListener on video elements. Is it possible to bind this context to document inside Array.prototype.forEach method when deleting eventListener? If I saved the necessary context into new variable then I got succeed. But then I'm trying bind, my IDE is saying 'Potentially invalid usage of this'.

Code snippet:

Gallery.prototype = {
  setCurrentPicture: function(currentPhoto) {
        var self = this;

        Array.prototype.forEach.call(container.children, function(item) {
          if (item.tagName === 'VIDEO') {
            document.removeEventListener('click', self.togglePlayVideo);
          }
          if (item.tagName === 'VIDEO' || item.tagName === 'IMG') {
            container.removeChild(item);
          }
        });

       if (pictures[currentPhoto] instanceof Video) {
          var video = document.createElement('video');
          ....
          document.addEventListener('click', self.togglePlayVideo);
        }
    },
},

 togglePlayVideo: function(e) {
      if (e.target.tagName === 'VIDEO') {
        return e.target.paused ? e.target.play() : e.target.pause();
      }
    }
}

In case of addition document.addEventListener('click', self.togglePlayVideo); I can use bind instead of self: document.addEventListener('click', this.togglePlayVideo.bind(this).

Can I use bind in removeEventListener? document.removeEventListener('click', this.togglePlayVideo.bind(this);

2
  • 2
    What is your question? (And can you please format your code properly) Commented Dec 22, 2015 at 18:44
  • when you write something like var self = this; u are using lexacal scope. if you want to set "this" to a particular value when you call your function you can use "function_name.apply(what_supposed_to_be_this, function_arguments)". And you obviously don't need to use self = this! Commented Dec 22, 2015 at 18:46

2 Answers 2

2

The best for you is to get familiar with what is "this" and what is "bind". You can do this by reading this brilliant description

and second part

To cut a long story short - when you declare a function with "this" like this:

  1. in defaul case "this" will be the Window object

    var f = function(){return this;};

    f(); //will return Window object

  2. when an object owns a link to your function like this:

    var f = function(){return this;};

    var o = {func: f};

    o.func(); // will return the "o" object becuase "this" becomes o object

  3. when you use explicit binding like call/apply you'll set this to a particular value like this:

    var f = function(){return this;};

    var obj = {};

    f.call(obj); // will return your obj

  4. and there is so called "hard binding". used like this:

    var f = function(){return this;};

    var obj1 = {num:1};

    var obj2 = {num:2};

    var boundFunc = f.bind(obj1); //now it's hardbound to obj1

    //let's try to switch this by using "call"

    boundFunc.call(obj2); // will return obj1, because it's hardbound

  5. and this can be affected when function is called with "new" keyword:

    f = function(){ this.a =1; this.b =2; };

    var obj = new f(); // will set brand new object as "this" and return it

    //so we will get {a:1, b:2} object as a result

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

5 Comments

thanks for the answer, the problem is that I'm using method of object inside other method of those object, and inside forEach loop I have this = undefined.
if you refer to case #4 (hardbinding) you'll see that "bind" returns a new function which is bound to a value you passed to "bind" and that bound function won't ever loose it's this. hope this helps
I'm also have tried to use static method: document.removeEventListener('click', Gallery.togglePlayVideo); But not sure that in this case event listener would be removed from particular gallery from which it has been added to document
I have this in constructor: this.togglePlayVideo = this.togglePlayVideo.bind(this);
You shold have a link to your callback function (var cb = function(){your_callback_code}), then you should find an element with var elem = document.getElementById('my-input') (or document.getElementsByClassName) and then to remove the listener you call elem.removeEventListener('click', callback)
0

I should add bind this to Array.prototype.forEach.call instead of implementing this to callback function.

 Array.prototype.forEach.call(container.children, function(item) {
          if (item.tagName === 'VIDEO') {
            document.removeEventListener('click', this.togglePlayVideo);
          }
          if (item.tagName === 'VIDEO' || item.tagName === 'IMG') {
            container.removeChild(item);
          }
        }.bind(this));

Thanks to all for the answers.

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.