Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
363 views
in Technique[技术] by (71.8m points)

javascript - How to execute different partsof the JS code in one scope

I have several script blocks depend on each other. I need to perform them in one scope.

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 'test is not defined' error. It seems that the code is executed in different scopes. Why is this happening?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Edit: Bergi pointed out my original answer was wrong, he is correct. Since eval runs in its own scope and the function constructor still runs in function scope according to the spec this is not possible with either.

While I have done this sort of thing myself several times with node.js using the vm module where you get much finer grain of control over where your code executes, it seems browsers require a different approach.

The only way you can share variables in such a way is to do so in the global scope of JavaScript execution (possibly, in an iframe). One way you could do this is script tag injection.

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 this code in action)

As for the scope wrapper, instead of injecting them in the same frame inject them in another iframe. That will scope their window object to that iframe and will allow you to share context.

I humbly apologize for my previous answer, I misread the spec. I hope this answer helps you.

I'm leaving my previous answer here because I still believe it provides some insight into how eval and the Function constructor work.


When running code in non-strict mode eval runs in the current context of your page After your function declaration is done, the scope it was declared in dies, and with it the function.

Consider using the Function constructor and then .calling it

In your case that would 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 a reference directly from the spec:

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

If this code is run in the node.js consider using the vm module. Also note that this approach is still not secure in the way it'll allow code you run to change your code.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...