How to execute different parts of JS code in one area

I have several script blocks dependent on each other. I need to execute them in one area.

My attempt:

var scopeWrapper = {}; with(scopeWrapper) { (function() { this.run = function(code) { eval(code); }; }).call(scopeWrapper); } scopeWrapper.run('function test() { alert("passed"); }'); scopeWrapper.run('test();'); 

I get the error "test not defined". It seems that the code is executing in different areas. Why is this happening?

+3
source share
2 answers

Edit: Bergie pointed out that my original answer was wrong, he's right. Since eval works in its field, and the function constructor still works in the function field according to spec , this is not possible with.

So far I have done this several times using node.js using the vm module, where you get a much finer grain of control over where your code is executing, it seems like the browser needs a different approach.

The only way to share variables this way is to do it in the global JavaScript execution area (possibly in an iframe). One way to do this is with the tag insert script.

 function run(code){ var sc = document.createElement("script"); sc.setAttribute("type","text/javascript"); sc.innerHTML = code; document.body.appendChild(sc); } run("var x = 5"); run("document.write(x)"); 

( here is the code in action )

As for the area wrapper, instead of pasting them into the same frame, paste them into another iframe . This will expand their window object to this iframe and allow you to share context.

I humbly apologize for my previous answer, I misunderstood the specification. Hope this answer helps you.

I leave my previous answer here because I still believe that it gives some insight into how eval and Function constructors work.


When you run the code in non-strict mode, eval is executed in the current context of your page. After the function declaration is completed, the area in which it was declared dies, and with it the function.

Consider using the function constructor and then .call ing it

In your case, it will be something like:

 var scopeWrapper = {}; scopeWrapper.run = function(code){ var functionToRun = new Function(code); functionToRun.call(scopeWrapper); } scopeWrapper.run('this.test = function() { alert("passed"); }'); scopeWrapper.run("this.test()") 

Here is the link directly from the specification:

If there is no call context or if the eval code is not evaluated by a direct call (15.1.2.1.1) for the eval function, Initialize the execution context as if it were a global execution context using the eval code as C, as described in 10.4.1.1.

If this code is running in node.js, consider using the vm module. Also note that this approach is still unsafe in how it will allow you to run code to modify your code.

+8
source

test exists only in the scope of this.run and only during a call:

 // global scope (function(){ // local scope (equivalent of your "run" function scope) eval('function f(){};'); console.log(f); // prints "function f(){}" })(); console.log(f); // prints "ReferenceError: f is not defined" 

Each run call creates a new area in which each code is evaluated separately.

0
source

Source: https://habr.com/ru/post/1493563/


All Articles