1

I began writing my own basic JavaScript library for personal use and distribution a few days ago, but I am having trouble with one of the methods, specifically bind().

Within the method itself, this refers to the library, the object.

I went to Google and found function.call(), but it didn't work out the way I planned it--it just executed the function.

If you take a look at another method, each(), you'll see that it uses call() to pass values.

I also tried the following:

f.arguments[0]=this;

My console throws an error, saying it cannot read '0' of "undefined".

I would like to be able to pass this (referencing the library--NOT THE WINDOW) to use it in the event listener.

You can see it starting at line 195 of the JavaScript of this JSFiddle.

Here it is as well:

bind:function(e,f){
    if(e.indexOf("on")==0){
        e=e.replace("on","");
    }
    if(typeof f==='function'){
            /*Right now, 'this' refers to the library
            How can I pass the library to the upcoming eventListener?
            */
            //f=f(this); doesn't work
            //f.call(this); //doesn't work
        
            //this.target refers to the HTMLElement Object itself, which we are adding the eventListener to
        //the outcome I'm looking for is something like this:
        /*$('h3').which(0).bind(function({
            this.css("color:red");
        });*/
        //(which() defines which H3 element we're dealing with
        //bind is to add an event listener
            this.target.addEventListener(e,f,false)
    }
    return this;
},
3
  • Could you please put the relevant code in this post here? A fiddle is nice for demonstration, but we're not going to go there and scan trough 200+ loc only for understanding the problem Commented Jul 7, 2013 at 22:04
  • 1
    Have you seen JavaScript's .bind() method, which "[c]reates a new function that, when called, has its this keyword set to the provided value"? Alternatively, your library .bind() could pass its own proxy function to addEventListener(), and then that function could call f using .call() or .apply(). Commented Jul 7, 2013 at 22:12
  • No, I hadn't until now, but issues may arise because I need this library to be compatible with Opera 9.5. Oh, and what do you mean about .call() and .apply()? I've never heard the term "proxy function" before. Commented Jul 7, 2013 at 22:18

3 Answers 3

1

If, as per your comments, you don't want to use .bind(), rather than directly passing f to addEventListener() you could pass another function that in turn calls f with .call() or .apply():

if(typeof f==='function'){
    var _this = this;
    this.target.addEventListener(e,function(event){
        f.call(_this, event);
    },false)
}

Doing it this way also lets your library do any extra event admin, e.g., pre-processing on the event object to normalise properties that are different for different browsers.

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

7 Comments

Note that a typeof test may not suit, since the function may be a host method. In that case, typeof may not return function though it is callable.
@RobG: I thougt the typof operator was the only thing ES5 gave us to determine whether an object is callable? (Not considering IE jScript of course)
@Bergi—yes, but host objects aren't governed by ES5: …an ECMAScript program will provide … certain environment-specific host objects, whose description and behaviour are beyond the scope of this specification. ;-) In practice, IE doesn't respect typeof in regard to host objects that are ActiveX objects (at least up to IE 8, dunno about after that) returning things like unknown and object for callable methods.
@RobG: While it does not describe their behaviour, it does specify how typeof does work on them: "For an Object (native or host) that does implement [[Call]] return "function"" (§11.4.3). And yes, IE does not respect the spec, but we knew that already.
@Bergi— the spec tries to have it both ways. It can't say host objects are outside the spec, then start specifying what they must do. The growth of javascript should not be restricted by ECMAScript. I can't fault IE 8 and lower on this because they're ES ed 3 browsers and conform in this regard (though of course have other quirks).
|
1

So in this particular case you actually want to call JavaScript's built in bind method that all functions have.

f = f.bind(this);

f will be a new function with it's this argument set to whatever you passed into it.

3 Comments

I had no idea that bind() was an actual method, but as I look at the compatibility with it, is there another way of doing this to support older versions of browsers (specifically Opera 9.5 or later).
@RickyYoder - You will have to do what nnnnnn has said to do in his answer. This is essentially what libraries like jQuery do.
Gotcha! Thanks for new knowledge, though!
0

Replace f=f(this); with f.apply(this);

Look at underscore code, here: https://github.com/jashkenas/underscore/blob/master/underscore.js#L596

2 Comments

That won't work because either way it calls the f function immediately - it would need to be done in conjunction with other changes. The underscore code you linked to has a different purpose to the OP's.
mmm you are right... my bad. Actually, this is what he is looking: github.com/jquery/jquery/blob/master/src/core.js#L693

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.