tags:

views:

11922

answers:

10

Problem: I call my javascript function, and sometimes I get the error 'myFunction is not defined'.

But it is defined.

For example. I'll occasionally get 'copyArray is not defined' even in this example:

function copyArray( pa ) {
    var la = [];
    for (var i=0; i < pa.length; i++)
     la.push( pa[i] );
    return la;
}

Function.prototype.bind = function( po ) {
    var __method = this;
    var __args = [];

    // sometimes errors -- in practice I inline the function as a workaround
    __args = copyArray( arguments );

    return function() {
     /* bind logic omitted for brevity */
    }
}

As you can see, copyArray is defined right there, so this can't be about the order in which script files load.

I've been getting this in situations that are harder to work around, where the calling function is located in another file that should be loaded after the called function. But this was the simplest case I could present, and appears to be the same problem.

It doesn't happen 100% of the time, so I do suspect some kind of load-timing-related problem. But I have no idea what.

@Hojou: That's part of the problem. The function in which I'm now getting this error is itself my addLoadEvent, which is basically a standard version of the common library function.

@James: I understand that, and there is no syntax error in the function. When that is the case, the syntax error is reported as well. In this case, I am getting only the 'not defined' error.

@David: The script in this case resides in an external file that is referenced using the normal <script src="file.js"></script> method in the page's head section.

@Douglas: Interesting idea, but if this were the case, how could we ever call a user-defined function with confidence? In any event, I tried this and it didn't work.

@sk: This technique has been tested across browsers and is basically copied from the prototype library.

+3  A: 

My guess is, somehow the document is not fully loaded by the time the method is called. Have your code executing after the document is ready event.

Per Hornshøj-Schierbeck
A: 

A syntax error in the function -- or in the code above it -- may cause it to be undefined.

James Curran
If that was the case, it would never work. Occasional failure is not explainable with a syntax error.
Tomalak
+2  A: 

It shouldn't be possible for this to happen if you're just including the scripts on the page. The "copyArray" function should always be available when the JS starts executing no matter if it is declared before or after it -- unless you're loading the JS files in dynamically with a dependency library? There are all sorts of problems with timing if that's the case.

David McLaughlin
I have not been able to reproduce -- or even experience -- this problem for a while, so I'm going to assume that it was my mistake.
harpo
A: 

Have you tried using an anonymous function to protect your local symbol table? Something like:

(function() {
function copyArray(pa) {
    // Details
}

Function.prototype.bind = function ( po ) {
    __args = copyArray( arguments );
}
})();

This will create a closure that includes your function in the local symbol table, and you won't have to depend on it being available in the global namespace when you call the function.

Douglas Mayle
+2  A: 

You're changing the prototype of the built-in 'function' object? It's possible you're running into a browser bug or race condition by modifying a fundamental built-in object. Have you tested this in multiple browsers?

sk
A: 

I'm afraid, when you add a new method to a Function class (by prtotyping), you actually adding it to all declared functions, AS WELL AS to your copyAraay(). In result your copyArray() function gets recursivelly self-referenced. I.e. there should exist copyArray().bind() method, which is calling itself.

In this case some browsers might prevent you from creating such reference loops and fire "function not defined" error.

Inline code would be better solution in such case.

Thevs
+1  A: 

This doesn't solve your original problem, but you could always replace the call to copyArray() with:

__args = Array.prototype.slice.call(arguments);

More information available from Google.

I've tested the above in the following browsers: IE6, 7 & 8B2, Firefox 2.0.0.17 & 3.0.3, Opera 9.52, Safari for Windows 3.1.2 and Google Chrome (whatever the latest version was at the time of this post) and it works across all browsers.

Grant Wagner
Thanks for the tip. I can use that in a number of places. However, I was really just using this function as an example. The one that's troubling me now is entirely different.
harpo
+1  A: 

Have you tried verifying your code with JSLint? It will usually find a ton of small errors, so the warning "JSLint may hurt your feelings" is pretty spot on. =)

Jan Aagaard
A: 

Jan,

Thank you very much!! After it hurt my feelings, it saved my code! I took out possibly offending pieces until all that was left was advisories and warnings, but no errors, and the code worked! What a find!

Bill

+1  A: 

I had this function not being recognized as defined in latest Firefox for Linux, though Chromium was dealing fine with it.

What happened in my case was that I had a former SCRIPT block, before the block that defined the function with problem, stated in the following way:

<SCRIPT src="mycode.js"/>

(i.e. without the closing tag).

I had to redeclared this block in the following way:

<SCRIPT src="mycode.js"></SCRIPT>

And then what followed worked fine... weird huh ?

Niloct