238

I wanted to call a function defined in a first.js file in second.js file. Both files are defined in an HTML file like:

<script type="text/javascript" src="first.js"></script>
<script type="text/javascript" src="second.js"></script>

I want to call fn1() defined in first.js in second.js. From my searches answers were if first.js is defined first it is possible, but from my tests I haven't found any way to do that.

Here is my code:

second.js

document.getElementById("btn").onclick = function() {
    fn1();
}

first.js

function fn1() {
    alert("external fn clicked");
}
informatik01
  • 16,038
  • 10
  • 74
  • 104
m0j1
  • 4,067
  • 8
  • 31
  • 54
  • 11
    So call it, there is nothing special as long as it is in global scope. – epascarello Sep 21 '14 at 19:22
  • 1
    We are all doing this a thousand of times per day. If you can't, there must be a problem with your first.js: Check whether it is loaded at all into your browser, and if yes, whether there was a syntax error while parsing it (both can be seen in the developer's toolbar of your browser) – rplantiko Sep 21 '14 at 19:22
  • 2
    It should work - http://stackoverflow.com/questions/3809862/can-we-call-the-function-written-in-one-javascript-in-another-js-file – theonlygusti Sep 21 '14 at 19:22
  • 2
    That should work. Please edit your question to tell us what happens when you run this using the JavaScript console in Chrome or Firefox/Firebug. (Um, and check that you spelled the function name correctly.) – Bob Brown Sep 21 '14 at 19:22
  • 1
    please see here http://plnkr.co/edit/?p=preview – sylwester Sep 21 '14 at 19:25
  • 2
    If it doesn't work, I guess you are doing something wrong. Given the information in your question, it's impossible want it is though. – Felix Kling Sep 21 '14 at 19:31
  • Thanks for the answers , I checked the console , no errors. checked spelling, no errors – m0j1 Sep 21 '14 at 19:35
  • 2
    Should the actual code. – epascarello Sep 21 '14 at 19:47
  • 1
    How are you checking, show us the function in `first.js`, and you calling it in `second.js`. – Spencer Wieczorek Sep 21 '14 at 19:51
  • I modified it to get me more clarify results and the console throws error when calling fn1() : 'fn1() is not defined'. I edited the question to show a sample of what I'm trying to do. – m0j1 Sep 21 '14 at 19:56
  • So it seems it works fine, I was just experimenting a file located on a wrong location with the same name and I just wasted 2 hours of my project! Sorry everyone and thanks for your kind answers – m0j1 Sep 21 '14 at 20:06
  • Possible duplicate of [Can we call the function written in one JavaScript in another JS file?](https://stackoverflow.com/questions/3809862/can-we-call-the-function-written-in-one-javascript-in-another-js-file) – funky-future Mar 29 '18 at 16:24
  • It should work. Test it here: https://codepen.io/constagorgan/project/editor/ARakvM – Consta Gorgan Sep 17 '18 at 14:08

17 Answers17

236

A function cannot be called unless it was defined in the same file or one loaded before the attempt to call it.

A function cannot be called unless it is in the same or greater scope then the one trying to call it.

You declare function fn1 in first.js, and then in second you can just have fn1();

1.js:

function fn1 () {
    alert();
}

2.js:

fn1();

index.html :

<script type="text/javascript" src="1.js"></script>
<script type="text/javascript" src="2.js"></script>
Neuron
  • 5,141
  • 5
  • 38
  • 59
Fernando Mendez
  • 2,559
  • 1
  • 10
  • 7
  • 7
    So what's the best way to manage all this in a production application? – Costa Michailidis Jul 31 '16 at 12:03
  • 47
    this doesn't work for me. Gives an error that fn1() is not defined – Aayushi Jun 03 '17 at 11:20
  • 14
    This doesn't work for me as well. Is there any work around except using jquery getscript as its suggest a bad practice? – Vandolph Reyes Jun 10 '17 at 11:42
  • 33
    Why is this the accepted answer with 82 votes if it doesn't really work? – Daniel Feb 26 '18 at 22:45
  • 1
    Works fine for me. – Alan Smith Mar 12 '18 at 11:08
  • 43
    If this is not working for you, chances are you defined the function within something else. For instance, I had my function within a `$(document).ready(function() {...})` block, and it did not work. I moved it and it worked like a charm. – Michael Ziluck Jul 24 '18 at 13:07
  • 1
    It wont work if u have a .mjs file instead of .js file or you export function f1 . I was doing both of those – Aseem Mar 08 '19 at 06:49
  • Maybe you import 2.js before 1.js. For the function in 1.js to be callable by another script, 1.js should have been imported in index.html first. – picmate 涅 May 07 '20 at 17:35
  • Works for me. Don't make the mistake I did: using nodejs import/export syntax: ` export function fn1 () { alert(); } ` – kohane15 Nov 25 '20 at 05:36
  • Thanks @MichaelZiluck! In my case I had it in $(document).ready. I just left it there but changed it to be: var SaveShippingAddress = function(){ ... } and that worked. – Jcis Sep 14 '21 at 21:49
  • 1
    @MichaelZiluck What if you need to define the function in `jQuery(document).ready(function(${...` else the function itself won't work? – Benjamin Carafa Jul 05 '22 at 20:46
55

You could consider using the es6 import export syntax. In file 1;

export function f1() {...}

And then in file 2;

import { f1 } from "./file1.js";
f1();

Please note that this only works if you're using <script src="./file2.js" type="module">

You will not need two script tags if you do it this way. You simply need the main script, and you can import all your other stuff there.

tm2josep
  • 599
  • 5
  • 10
  • 4
    With Safari, I get `cross-origin script load denied by cross-origin resource sharing policy` – kakyo Apr 23 '20 at 09:54
  • 1
    With older browsers you may not be able to use the es6 import syntax. You could use Babel if it makes it easier for you. – tm2josep Jun 18 '20 at 18:14
  • How to (export and) import the whole content of the `file1.js` ? – payne Oct 21 '20 at 16:45
34

1st JS:

function fn(){
   alert("Hello! Uncle Namaste...Chalo Kaaam ki Baat p Aate h...");
}

2nd JS:

$.getscript("url or name of 1st Js File",function(){
fn();
});
Nimantha
  • 6,405
  • 6
  • 28
  • 69
Akshay Tyagi
  • 528
  • 4
  • 7
26

You can make the function a global variable in first.js and have a look at closure and do not put it in document.ready put it outside

you can use ajax too

    $.ajax({
      url: "url to script",
      dataType: "script",
      success: success
    });

same way you can use jquery getScript

$.getScript( "ajax/test.js" )
  .done(function( script, textStatus ) {
    console.log( textStatus );
  })
  .fail(function( jqxhr, settings, exception ) {
    $( "div.log" ).text( "Triggered ajaxError handler." );
});
Gildas.Tambo
  • 22,173
  • 7
  • 50
  • 78
  • 9
    Beginners never try doing anything like this. These are bad practices to be avoided. As long as both are referenced by the web page, yes. You simply call the functions as if they are in the same JS file. – Ananda May 18 '16 at 16:30
  • 1
    The only issue is, it doesn't include the header for some reason. – Si8 Mar 31 '17 at 14:08
  • Cannot use import statement outside a module – Alfa Rojo Feb 23 '22 at 17:41
19

declare function in global scope with window

first.js

window.fn1 = function fn1() {
    alert("external fn clicked");
}

second.js

document.getElementById("btn").onclick = function() {
   fn1();
}

include like this

<script type="text/javascript" src="first.js"></script>
<script type="text/javascript" src="second.js"></script>
taoufiqaitali
  • 460
  • 5
  • 10
  • Is this recommended? What If I have 1000 functions. What I'm trying to do is to have a single JavaScript file to hold all event listeners. But to make that work I would have to declare each function in global scope as you suggest. Wouldn't this slow things down? – programming_ritual Jun 11 '21 at 13:16
10

use "var" while creating a function, then you can access that from another file. make sure both files are well connected to your project and can access each other.

file_1.js

var firstLetterUppercase = function(str) {
   str = str.toLowerCase().replace(/\b[a-z]/g, function(letter) {
      return letter.toUpperCase();
   });
   return str;
}

accessing this function/variable from file_2.js file

firstLetterUppercase("gobinda");

output => Gobinda

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Gobinda Nandi
  • 457
  • 7
  • 18
7

It should work like this:

1.js

function fn1() {
  document.getElementById("result").innerHTML += "fn1 gets called";
}

2.js

function clickedTheButton() {
  fn1();
} 

index.html

<html>
  <head>
  </head>
  <body>
    <button onclick="clickedTheButton()">Click me</button>
    <script type="text/javascript" src="1.js"></script>
    <script type="text/javascript" src="2.js"></script>
  </body>
 </html>

output

Output. Button + Result

Try this CodePen snippet: link .

Consta Gorgan
  • 549
  • 6
  • 22
7

Please note this only works if the

<script>

tags are in the body and NOT in the head.

So

<head>
...
<script type="text/javascript" src="first.js"></script>
<script type="text/javascript" src="second.js"></script>
</head>

=> unknown function fn1()

Fails and

<body>
...
<script type="text/javascript" src="first.js"></script>
<script type="text/javascript" src="second.js"></script>
</body>

works.

user213979
  • 99
  • 1
  • 5
  • OH THAT'S WHY! your answer was really helpful as I couldn't figure out why, although my scripts were in correct order, the functions still were undefined. Why does this happen, though? – Artem Nov 23 '22 at 12:00
5

This is actually coming very late, but I thought I should share,

in index.html

<script type="text/javascript" src="1.js"></script>
<script type="text/javascript" src="2.js"></script>

in 1.js

fn1 = function() {
    alert("external fn clicked");
}

in 2.js

fn1()
Obsidian
  • 3,719
  • 8
  • 17
  • 30
Ishaq Yusuf
  • 59
  • 1
  • 1
  • Please see the OP's comment under the question: "...I was just experimenting [with] a file located on a wrong location with the same name...". – traktor Sep 29 '19 at 05:18
3

Use cache if your server allows it to improve speed.

var extern =(url)=> {           // load extern javascript
    let scr = $.extend({}, {
        dataType: 'script',
        cache: true,
        url: url
    });
    return $.ajax(scr);
}
function ext(file, func) {
    extern(file).done(func);    // calls a function from an extern javascript file
}

And then use it like this:

ext('somefile.js',()=>              
    myFunc(args)
);  

Optionally, make a prototype of it to have it more flexible. So that you don't have to define the file every time, if you call a function or if you want to fetch code from multiple files.

Thielicious
  • 4,122
  • 2
  • 25
  • 35
3

first.js

function first() { alert("first"); }

Second.js

var imported = document.createElement("script");
imported.src = "other js/first.js";  //saved in "other js" folder
document.getElementsByTagName("head")[0].appendChild(imported);


function second() { alert("Second");}

index.html

 <HTML>
    <HEAD>
       <SCRIPT SRC="second.js"></SCRIPT>
    </HEAD>
    <BODY>
       <a href="javascript:second()">method in second js</a><br/>
       <a href="javascript:first()">method in firstjs ("included" by the first)</a>
    </BODY>
</HTML>
Afsar
  • 49
  • 5
1
window.onload = function(){
    document.getElementById("btn").onclick = function(){
        fn1();
    }
   // this should work, It calls when all js files loaded, No matter what position you have written
});
phpnerd
  • 850
  • 1
  • 10
  • 25
  • 2
    Although your code snippet might solve the issue, you should describe what’s the purpose of your code (how it solves the problem). Furthermore, you might want to check https://stackoverflow.com/help/how-to-answer – Ahmad F Mar 14 '18 at 10:58
1
// module.js
export function hello() {
  return "Hello";
}

// main.js
import {hello} from 'module'; // or './module'
let val = hello(); // val is "Hello";

reference from https://hype.codes/how-include-js-file-another-js-file

Min Thant
  • 39
  • 1
1

My idea is let two JavaScript call function through DOM.

The way to do it is simple ... We just need to define hidden js_ipc html tag. After the callee register click from the hidden js_ipc tag, then The caller can dispatch the click event to trigger callee. And the argument is save in the event that you want to pass.

When we need to use above way ?

Sometime, the two javascript code is very complicated to integrate and so many async code there. And different code use different framework but you still need to have a simple way to integrate them together.

So, in that case, it is not easy to do it.

In my project's implementation, I meet this case and it is very complicated to integrate. And finally I found out that we can let two javascript call each other through DOM.

I demonstrate this way in this git code. you can get it through this way. (Or read it from https://github.com/milochen0418/javascript-ipc-demo)

git clone https://github.com/milochen0418/javascript-ipc-demo
cd javascript-ipc-demo
git checkout 5f75d44530b4145ca2b06105c6aac28b764f066e

Anywhere, Here, I try to explain by the following simple case. I hope that this way can help you to integrate two different javascript code easier than before there is no any JavaScript library to support communication between two javascript file that made by different team.

<html>
<head>
    <link rel="stylesheet" type="text/css" href="css/style.css" />
</head>
<body>
    <div id="js_ipc" style="display:none;"></div>
    <div id="test_btn" class="btn">
        <a><p>click to test</p></a>
    </div>    
</body>
<script src="js/callee.js"></script>
<script src="js/caller.js"></script>
</html>

And the code css/style.css

.btn {
    background-color:grey;
    cursor:pointer;
    display:inline-block;
}

js/caller.js

function caller_add_of_ipc(num1, num2) {
    var e = new Event("click");
    e.arguments = arguments;
    document.getElementById("js_ipc").dispatchEvent(e);
}
document.getElementById("test_btn").addEventListener('click', function(e) {
    console.log("click to invoke caller of IPC");
    caller_add_of_ipc(33, 22);      
});

js/callee.js

document.getElementById("js_ipc").addEventListener('click', (e)=>{
    callee_add_of_ipc(e.arguments);
});    
function callee_add_of_ipc(arguments) {
    let num1 = arguments[0];
    let num2 = arguments[1];
    console.log("This is callee of IPC -- inner-communication process");
    console.log( "num1 + num2 = " + (num1 + num2));
}
Milo Chen
  • 3,617
  • 4
  • 20
  • 36
1

better late than never

(function (window) {const helper = { fetchApi: function () { return "oke"}
   if (typeof define === 'function' && define.amd) {
    define(function () { return helper; });
   }
   else if (typeof module === 'object' && module.exports) {
    module.exports = helper;
  }
  else {
    window.helper = helper;
  }
}(window))

index html <script src="helper.js"></script> <script src="test.js"></script>

in test.js file helper.fetchApi()

muh rifai
  • 11
  • 1
0

I have had same problem. I have had defined functions inside jquery document ready function.

$(document).ready(function() {
   function xyz()
   {
       //some code
   }
});

And this function xyz() I have called in another file. This doesn't working :) You have to defined function above document ready.

Meldo
  • 146
  • 1
  • 6
  • This is downvoted but is the same problem I had. My solution is to take the function out of the $(document).ready() function. – Ben Nov 26 '20 at 17:27
-1

TLDR: Load Global Function Files first, Then Load Event Handlers

Whenever you are accessing an element within a JS file or <script> block, it is essential to check to make sure that element exists, i.e., jQuery's $(document).ready() or plain JS's document.addEventListener('DOMContentLoaded', function(event)....

However, the accepted solution does NOT work in the event that you add an event listener for the DOMContentLoaded, which you can easily observe from the comments.

Procedure for Loading Global Function Files First

The solution is as follows:

  • Separate the logic of your JS script files so that each file only contains event listeners or global, independent functions.
  • Load the JS script files with the global, independent functions first.
  • Load the JS script files with event listeners second. Unlike the other previous files, make sure to wrap your code in document.addEventListener('DOMContentLoaded', function(event) {...}). or document.Ready().
HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133