0

I want to load a javascript function from a text file over ajax (using jQuery) but cannot seem to be able to get it right.

This is my javascript function which I want to load from a text file (abc.js):

function my_alert() { alert 1; }

This is how I use ajax to read the file:

$.getScript('abc.js', function (script) { 
    var loaded_function = ???
});

How do I assign loaded_function so that I can call my_alert using loaded_function.my_alert()?

EDIT

The reason I do not want to create new <script> tags or use $.getScript is that my_alert then lives in the global context. I want it to only live inside the { } function scope.

Is this possible?

pac w
  • 647
  • 6
  • 17
  • 1
    Thats not how this works - onload your `my_alert` function will be available in your global context. So... `loaded_function = my_alert` would work. If its a string, you can parse it using `eval` ( **dangerous** ) or the `Function` constructor. – somethinghere Apr 26 '16 at 13:59
  • Look at [this](http://stackoverflow.com/questions/86513/why-is-using-the-javascript-eval-function-a-bad-idea) SO discussion. – Jeroen Heier Apr 26 '16 at 14:01
  • Why would you want to do this? Why not use ES6 modules? – Chiru Apr 26 '16 at 14:02
  • 2
    I'm not saying you should use `eval`, but everyone saying "eval is *dangerous*" needs to qualify that with "*if* it is used on user input". Don't fear what you don't understand. – Mulan Apr 26 '16 at 14:03
  • @naomik And javascript is a client based, user side language. _Its the user who is running it_. Regardless of how you look at it, _eval_ is simply something you should avoid if _at all_ possible and otherwise use very, very carefully. – somethinghere Apr 26 '16 at 14:04
  • @somethinghere unless the user specifies the context for this program, you cannot pretend to know how/where it is run. JavaScript is everywhere now. – Mulan Apr 26 '16 at 14:10
  • @somethinghere if my program is `eval("console.log('hello');");` and that is run by the user, yes that is a dumb program, but it is not *dangerous* just because it is evaluated by a user's browser. – Mulan Apr 26 '16 at 14:11
  • @naomik Still, get in line and start telling everyone who asks that `eval` is the programming incarnation of the devil and any other representation of evil into one! Actually, no, it's not that bad, I know, but confusing people with the argument that `eval` is only dangerous in certain situation might make starting developers rely or use it without knowing the inherent dangers. It's better to avoid eval altogether than using it but not knowing the caveats :) – somethinghere Apr 26 '16 at 14:12
  • If I run var loaded_function = eval(script); then loaded_function is undefined. I know I can do this: eval(script) and then just call my_alert() but I want to assign my_alert to loaded_function. – pac w Apr 26 '16 at 14:12
  • I cannot use ES6 modules nor RequireJS. – pac w Apr 26 '16 at 14:13
  • @pacw If you had read the jQuery documentation, you might have seen that jQuery will execute your script in global context _on load_, so once your scripts has loaded your function will be available as `my_alert` in _global context_. So basically all you need to do is `loaded_function = my_alert` and you are sorted. – somethinghere Apr 26 '16 at 14:13
  • @somethinghere Hmm.. true. What if I don't want it to be in global context? – pac w Apr 26 '16 at 14:21
  • @somethinghere I disagree that fear mongering is effective to teach people about programming. I am willing to bet 99 out of 100 programmer that say "eval is bad" are just being parrots and have no idea what they're talking about. Can you use eval insecurely? Yes. Is writing a secure program difficult in general? Yes. Is it easier to parrot other people than to adopt the burden of actually educating someone? Yes. Should you scare people about things you don't understand? No. – Mulan Apr 26 '16 at 14:36
  • @pacw I don't think this is possible as you are asking to evaluate anonymous functions in that case, which just won't do, and you can't directly get some code in. The only way to do this is to load the file as text and then run it through eval in context - As the discussion above points out, that's not ideal. It could be safe, but in most circumstances you would want to find another solution. Have a try that way. – somethinghere Apr 26 '16 at 14:49
  • @somethinghere lol #triggered. How about people that recommend ajax solutions? Though easily mitigated now, most people don't bother to mention that XSS and CSRF attacks are a serious risk. Even on this very page, there are several mentions of ajax but nothing pertaining to how it's *possibly* "dangerous". How about mentioning threats to user privacy when recommending cookies? Are cookies *dangerous* because they could be used wrongfully? – Mulan Apr 26 '16 at 14:50
  • @somethinghere. I think you nailed it there. I don't want it to run the loaded function in the global context as I will be loading multiple files which may have functions which are named the same. – pac w Apr 26 '16 at 14:51
  • @naomik Let's not continue this slugmatch. I understand your point, and it's valid, it's just that these kind of complexities is what makes developing hard to understand when you're starting out. I'd rather hear 'dont use eval' than 'use eval only in the following 32 cases' (and then memorise where to use it!). Lets just say that eval is best left in the hands of people with experience :) – somethinghere Apr 26 '16 at 14:53
  • 1
    @somethinghere fair enough. My only hope is that the dialogue might change from "eval is *bad*" or "eval is *evil*" to "there are better/safer/faster ways to accomplish what your goal without using eval". It's okay to encourage people not to use it, but only because a better solution usually does exist. The reason provided should be accurate, but that doesn't mean it's going to be anymore overwhelming for a learner. Cheers. – Mulan Apr 26 '16 at 15:02
  • @naomik I wholeheartedly agree :) (apart from that bit about being overwhelming.. I think eval posses enough _potential_ threats to try to avoid new coders using it until they understand the implications, but thats really a minor difference. I really should stop rambling about this with you :) ) – somethinghere Apr 26 '16 at 15:04

4 Answers4

0

How do I assign loaded_function so that I can call my_alert using loaded_function.my_alert()?

Use the module pattern for this

# this is the module
function my_alert(){

    // Private section
    var loaded_function = ...

    // Public section which any instance can have access to  
    return{
       loaded_function: loaded_function
    };
}

Demo code:

var my_alert = (function() {

    // Private section
    function private() {
        console.log('Private function ...')
    }

    // Public section which any instance can have access to
    return {
        public: private
    };
})();

my_alert.public();

Load JS file and store it:

(function(url, callback){

    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function(){
        if(this.readyState == 4 && this.status == 200){
            // Your file data is now in the :
            // this.responseText;
        }
    }

    xhr.open("GET", url, true);
    xmlHTTP.send();

})("url");
CodeWizard
  • 128,036
  • 21
  • 144
  • 167
  • Well.. what I really want to do is load my js-code from a file (dynamically) and then set it to a variable. – pac w Apr 26 '16 at 14:15
  • Has nothing to do with this. load it with Ajax and save it on the local variable. – CodeWizard Apr 26 '16 at 14:16
  • Ajax.... (what ever) and when you have result build up your module in the callback of the Ajax – CodeWizard Apr 26 '16 at 14:17
  • How would you load the JavaScript file, using jquery/ajax, and save it on a local variable? – pac w Apr 26 '16 at 14:29
  • Ok. I feel a bit dense here but how does the text become javascript? Using jquery $.getScript it does this by using eval (i guess) which puts it on the global context. But if I do not want it on the global context but just assigned to a variable inside of the function which loads the text? – pac w Apr 26 '16 at 14:49
  • Exactly. jQuery already has it as JS. Using the native code you will have to inject it using – CodeWizard Apr 26 '16 at 14:50
  • jQuery is a better option here. – CodeWizard Apr 26 '16 at 14:51
-1

You either use eval (which is dangerous) like this:

$.getScript('abc.js', function (script) { 
    var loaded_function = eval(script);
});

or you can can use the normal assigning method

*this method will work only if the script contains a function definition like

function myFunction(){/* some code*/}

the code will be :

$.getScript('abc.js', function () { 
    var loaded_function= myFunction;   //not = myFunction()
});
AlhasanIQ
  • 183
  • 2
  • 9
-1

It's a good practice to wrap your function in an object. This way you could have e.g.:

var exposed = {
myFunc: function () {}
}

So, 'script' should be the function and assigning it to a var should expose its scope.

var loaded_function = script.exposed

To call it:

loaded_function.myFunc();
vpenkoff
  • 15
  • 3
-1

You can use this code:

$.get('abc.js', function(script) {
    var loaded_function = {};
    var function_list = [];
    // save names of defined functions
    for (var key in window) {
        if (typeof window[key] == 'function' && !window[key].toString().match(/\[native code\]/)) {
            function_list.push(key);
        }
    }
    // use global eval https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval
    var geval = eval;
    geval(script);
    for (var key in window) {
        if (typeof window[key] == 'function' && !window[key].toString().match(/\[native code\]/) &&
            function_list.indexOf(key) == -1) {
            loaded_function[key] = window[key];
            delete window[key];
        }
    }
    console.log(loaded_function.my_alert);
}, 'text');
jcubic
  • 61,973
  • 54
  • 229
  • 402
  • I didn't do the down vote but this looks kind of strange: var geval = eval; geval(script); ... geval is just a reference to eval so why do this instead of using eval directly? – pac w Apr 27 '16 at 07:04
  • I've found it here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval without it function don't appear in window because they are local to the function from which it was called. – jcubic Apr 27 '16 at 07:24