0

In file_b.js I have the function

function date_of_birth(target, selector, days) { // Do something }

In file_a.js I try to call the function with date_of_birth('a', 'b', 30) but I get the error: date_of_birth is not defined

So I tried it with:

window.date_of_birth = function date_of_birth(target, selector, days) { // Do something }

When I call window.date_of_birth('a', 'b', 30);, I get the error: window.date_of_birth is not a function

When I call console.log(window.date_of_birth);, I get undefined.

In both files I use:

$(document).ready(function() {

});

Why is my function not defined??

3 Answers3

1

Here in late 2020, you'd use modules to do this, either relying on the native support that's present in all modern major browsers, or bundlers like Webpack or Rollup.js that take code using module syntax and bundle it for older browsers.

With module syntax, in the simple case, you'd export the function you want to provide:

export function date_of_birth(/*...*/) {
    // ...
}

That's an exported function declaration, which creates a named export. Code in another module that wanted to use that function would import that function:

import { date_of_birth } from "./module-name.js";

There's a lot more to this topic, more on MDN or in Chapter 13 of my book JavaScript: The New Toys (links in my profile if interested).


Old answer:

In your original code, it's undefined because it's not a global. When you define a function within another function, as I take it you've done, like this:

$(document).ready(function() {
    function date_of_birth(target, selector, days) { // Do something }
});

...the function is only accessible within that ready callback, not globally.

When you changed it to:

$(document).ready(function() {
    window.date_of_birth = function date_of_birth(target, selector, days) { // Do something };
});

that does indeed make it a global, so the error tells us that the ready callback for the other file (where you're using the function) runs before the ready callback in that file (where you're defininig the function).

How to fix it:

  1. Pick a unique identifier for your app, say MyApp. (It doesn't have to be globally unique, it just has to A) Not be something defined in the browser environment, B) Not be something likely to be defined in the browser environment at some point in the future, and C) Not be something defined by any lib you use.) For instance, jQuery uses jQuery.

  2. In your file where you define this function, do this:

     var MyApp = MyApp || {};
     MyApp.date_of_birth = function date_of_birth() { /*...*/ };
    

    Or if you have shared functions for class-wide data or something that you want to keep private, you could use a wrapper function:

     var MyApp = MyApp || {};
     (function() {
         function privateWorkerFunction() {
         }
         MyApp.date_of_birth = function date_of_birth() { /*...*/ };
         // ...
     })();
    
  3. In your file where you use that, use it like this:

     MyApp.date_of_birth(/*...*/);
    
  4. Ensure that the file defining the function is before the file using it, put both at the end of the HTML (just before the closing </body> tag), and get rid of the ready callbacks (there's no need; if the scripts are at the end of the document, things are ready enough).

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thank you, that helped me a lot. It was even enough to remove the function from `ready()` and it also works without the unique identifier. –  Mar 07 '18 at 12:42
  • @RezaSaadati: Yes, but if you do that, you're creating a global for every function, and the global namespace is **really** crowded. Using a single identifier (`MyApp` in the example) helps you avoid conflicts. – T.J. Crowder Mar 07 '18 at 12:47
  • Good to know. Thank you, I will use your code. Could you please tell me what `MyApp || {};` stands for? –  Mar 07 '18 at 12:55
  • @RezaSaadati: I really should have explained that. :-) `var MyApp` will declare the variable if it hasn't already been declared and give it the initial value `undefined`. If it's *already* been declared (for instance, in another of your files), `var MyApp` does nothing. The `= MyApp || {}` sets the variable either to the value it already has (if that value isn't "falsy") or to a freshly-created object (`{}`). So if you use this in each of your files, the *first* file will create the variable and assign an object to it, and all the others will use the object that's already there. – T.J. Crowder Mar 07 '18 at 13:18
  • Thank you so much, this is soo useful!! In future I will always do it this way. –  Mar 08 '18 at 08:37
  • Could you explain #2 why you wrapped `MyApp.date_of_birth =` in an `anonymous self-invoking function`? Would it work the same without the wrapper? Also, in #3, could you show us how you would use `import`? – konyak Oct 04 '20 at 03:56
0

You need to specify file_b.js before file_a.js in your HTML page like this:

<script type="text/javascript" src="file_b.js"></script>
<script type="text/javascript" src="file_a.js"></script>

so that when you call date_of_birth('a', 'b', 30) from file_a.js it is already rendered through file_b.js.

Ankit Agarwal
  • 30,378
  • 5
  • 37
  • 62
0

when you declare function function date_of_birth(target, selector, days) { // Do something } you do not need to $(document).ready(function(){ }).

declare date_of_birth function outside of $(document).ready function and then try.

Bhavik Hirani
  • 1,996
  • 4
  • 28
  • 46