2

In order to be GDPR compliant I wrapped all affiliate scripts on our webshop inside functions and add them to a job queue.

After the user accepts our privacy policy I run all queued jobs. I want to run them in global scope so all declared variables are accessible in global scope because some affiliate scripts are depending on global variables (I know that's ugly ;) ).

I know, I could rewrite all the javascript code and declare the varibales in global scope and wrap the rest of the code inside a function. But then I would need to edit a lot of external modules (we are running a magento webshop and use external modules for including the affiliate scripts)

my current approach:

var jobQueue = [];
var add = function (fn) {
    jobQueue.push(fn);
    console.log("function pushed to queue");
};
var execute = function () {
    while ((curJob = jobQueue.pop()) !== undefined) {
        curJob();
        console.log("executed job");
    }
};

my problem is that some external scripts are depending on the variables declared inside my jobs. Is there any possibility to run the functions like the code was run globally?

I already found something like this but I could not make it work: Javascript eval on global scope? (this does not work with functions)

eval.call(window, x, y, z)
warch
  • 2,387
  • 2
  • 26
  • 43
  • How are `add` and `execute` function being called? – Thum Choon Tat Apr 24 '18 at 07:16
  • 2
    If they are your functions, you can just declare the variables differently (not use `var`). But to be honest, I would get rid of any code that requires your variables to be global. – GolezTrol Apr 24 '18 at 07:16
  • i do not like it too but i need this in order to get affiliate scripts working. i changet my code because of gdpr and declare / load the variables / scripts after the user accepts our privacy policy... however... the code which was run in global scope is now wrapped inside a function and called later... but when loading the external affiliate script it needs the variables in global scope – warch Apr 24 '18 at 07:21
  • i guess you have many function using the same variables,so by putting the variables in global execution context,all function can access the variable ? – Biswadev Apr 24 '18 at 07:22
  • @ThumChoonTat i am wrapping all my affiliate script on my webside inside a function block and add them to my job queue ... when the user accepts the privacy policy (because of gdpr) i execute all my queued jobs – warch Apr 24 '18 at 07:22
  • @BittuS see my first comment... my scripts were already running in global scope due compatibility with affiliate scripts, but in order to be gdpr compliant i need to wrap the code in functions and execute them after the user accepted our privacy policy... so there are no overlapping variables, otherwise the code would not have been working till now ;) – warch Apr 24 '18 at 07:25
  • @GolezTrol regarding function declaration... i just copied the code and simplified it... in my project these functions are declared in a requirejs module and returned as json... so you do not have to worry about this ;) – warch Apr 24 '18 at 07:27

2 Answers2

3

I found a possible solution but it is ugly:

I save the body of the function (How to get function body text in JavaScript?) to a string and evaluate it in window scope

var execute = function () {
    while ((curJob = jobQueue.pop()) !== undefined) {
        var entire = curJob .toString(); 
        var body = entire.slice(entire.indexOf("{") + 1, entire.lastIndexOf("}"));
        eval.call(window, body);
        console.log("executed job");
    }
};
warch
  • 2,387
  • 2
  • 26
  • 43
0

Variables in Javascript have 'function scope', meaning that if you declare a variable inside a function, it won't be accessible from outside that function. But when a variable doesn't exist inside a function, Javascript will look for that variable outside that function until it reaches the global object.

So variables declared in the global object are visible everywhere.

You can assign variables to the global scope just by declaring them in the global scope.

var pushing = "function pushed to queue";
var executed = "executed job";
var jobTitle = "... programing ...";

var jobQueue = [];
var add = function (fn) {
    jobQueue.push(fn);
    console.log( pushing );
};
var execute = function () {
    while ((curJob = jobQueue.pop()) !== undefined) {
        curJob();
        console.log( executed );
    }
};

// Lets add a Job
add( function(){ console.log( jobTitle ); } );

execute();

JS Bin

As you can see, the job added has access to the variable jobTitle that is declared in the global scope.

Hope it helps

RicardoAgra
  • 600
  • 1
  • 3
  • 13
  • thx for your answer but i do not want to edit all scripts on my website i am just wrapping all inlined affiliate scripts inside functions to run them at a different time (after the user accepts the privacy policy).... i know i could declare all variables needed in global scope manually but this would be too much effort because we are running multiple affiliate scripts rendered by some external modules (we are running a magento webshop)... i would need to edit all modules if i want to declare the variables in a different way – warch Apr 24 '18 at 07:31
  • If you need to access variables declared in a function somewhere else, you'll need to store them in a shared scope. The point of using an iife is to prevent global definitions. What you can do is declare a single object in the global space and store all your variables there. It's what jQuery does with $() – RicardoAgra Apr 24 '18 at 07:36