1

I'm writing a jQuery plugin, which similar to this,

$(this).each(function(){
    $el = $(this).find('.el')
    $el.click(function(){
       test();
    });
    function test() {
       console.log('test init');
    }
});

This works fine when $el is clicked

but when i use the test() outside of $el.click like this

$(this).each(function(){
    $el = $(this).find('.el')
    test();
    function test() {
       console.log('test init');
    }
});

I get type error undefined is not a function

PS: I'm coding in coffee, syntax/spelling isn't an issue here

6
  • 1
    because... test() isn't defined yet when it is called? JS executes lineraly, which is like "top-to-bottom". try moving test below the declaration, and tell me if it works. Commented Mar 24, 2012 at 7:52
  • i see, thanks so what would be the best way to keep the function below the whole code, but still activate it? Becuase it will look kind of ugly to bring a chunk of function on the top. Commented Mar 24, 2012 at 7:53
  • Exactly test is not defined yet and when you set .click event binding it works fine; also if I may ask why are you keeping the function definition inside the .each loop? just curious! hope this helps, cheers Commented Mar 24, 2012 at 7:55
  • ah, yeah, i got little carried away in coding with coffee, the indentation wasn't right, and by the time I found out, and put it out the loop, all functions becomes undefined. and since it was already 200 lines, i just kept going until this roadblock. thanks to Joseph for the solution, i definetly going to optimise the whole script afterwards. Commented Mar 24, 2012 at 8:02
  • 1
    The code you posted is fine. Function declarations are "hoisted" to the top of the enclosing scope. @Joseph: You are not correct, see this comment. Commented Mar 24, 2012 at 8:15

1 Answer 1

2

if your test() needs to execute immediately, then do this:

$(this).each(function(){
    $el = $(this).find('.el')

    (function test() {
       console.log('test init');
    }());                          //the "()" at the end executes the function
});

but test() won't be available from the outside world this way. it's somewhat "enclosed". if you need test to execute immediately and still be callable by others, do this:

$(this).each(function(){
    $el = $(this).find('.el')

    var test = (function testFunc() {
       console.log('test init');
       return testFunc;                //return itself to the variable "test"
    }());                              //execute
});
Sign up to request clarification or add additional context in comments.

2 Comments

For the last case you could also go var test = function() {[...]}; test();.
@dbaupp i considered that, but it would "look cleaner" if you had an immediately-invoked expression that was at the same time a declaration.

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.