Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a simple method of turning a global var into a local var?

Tags:

javascript

Let's say we have a function that looks like this:

const fn = () => x;

This function should return the value of x where x is available in the global scope. Initially this is undefined but if we define x:

const x = 42;

Then we can expect fn to return 42.

Now let's say we wanted to render fn as a string. In JavaScript we have toString for this purpose. However let's also say we wanted to eventually execute fn in a new context (i.e. using eval) and so any global references it uses should be internalized either before or during our call to toString.

How can we make x a local variable whose value reflects the global value of x at the time we convert fn to a string? Assume we cannot know x is named x. That said we can assume the variables are contained in the same module.

like image 554
maxcountryman Avatar asked Feb 10 '17 20:02

maxcountryman


People also ask

Can you change a global variable in a function?

Functions can access global variables and modify them. Modifying global variables in a function is considered poor programming practice. It is better to send a variable in as a parameter (or have it be returned in the 'return' statement).

How do you make a local variable a global variable?

Normally, when you create a variable inside a function, that variable is local, and can only be used inside that function. To create a global variable inside a function, you can use the global keyword.

Can local variable change global variable?

Local variables can only be accessed within the function or module in which they are defined, in contrast to global variables, which can be used throughout the entire program. In Python, a Global variable can be defined using the global Keyword, also we can make changes to the variable in the local context.

Can local and global variable be same?

It is usually not a good programming practice to give different variables the same names. If a global and a local variable with the same name are in scope, which means accessible, at the same time, your code can access only the local variable.


1 Answers

If you want lock certain variables while converting function to string, you have to pass that variables along the stringified function.

It could be implemented like this (written with types -- typescript notation)

const prepareForEval = 
  (fn: Function, variablesToLock: { [varName: string]: any }): string => {
    const stringifiedVariables = Object.keys(variablesToLock)
        .map(varName => `var ${varName}=${JSON.stringify(variablesToLock[varName])};`);

    return stringifiedVariables.join("") + fn.toString();
  }

Then use it like this

const stringifiedFunction = prepareForEval(someFunction, { x: x, y: y })

// you can even simplify declaration of object, in ES6 you simply write
const stringifiedFunction = prepareForEval(someFunction, { x, y })
// all variables you write into curly braces will be stringified
// and therefor "locked" in time you call prepareForEval()

Any eval will declare stringified variables and funtion in place, where it was executed. This could be problem, you might redeclare some variable to new, unknown value, you must know the name of stringified function to be able to call it or it can produce an error, if you redeclare already declared const variable.

To overcome that issue, you shall implement the stringified function as immediatelly executed anonymous function with its own scope, like

const prepareForEval = 
  (fn: Function, variablesToLock: { [varName: string]: any }): string => {
    const stringifiedVariables = Object.keys(variablesToLock)
        .map(varName => `var ${varName}=${JSON.stringify(variablesToLock[varName])};`);

    return `
      var ${fn.name} = (function() {
        ${stringifiedVariables.join("")}
        return ${fn.toString()};
      )(); 
    `;
  }

this modification will declare function and variables in separate scope and then it will assign that function to fn.name constant. The variables will not polute the scope, where you eval, it will just declare new fn.name variable and this new variable will be set to deserialized function.

like image 144
Rudolf Gröhling Avatar answered Oct 20 '22 15:10

Rudolf Gröhling