Javascript 使用jQuery加载脚本时维护作用域

Javascript 使用jQuery加载脚本时维护作用域,javascript,jquery,ajax,scope,Javascript,Jquery,Ajax,Scope,假设我有一个包含以下内容的文件“test.js”: var test = 'something'; 然后我有一个主脚本,需要加载test.js来获取测试变量 显然,这是可行的: $.ajax({dataType: "script", cache: true, url: 'test.js'}); 问题在于变量test存在于全局范围内。我很好奇是否有办法将其添加到对象中,并将其保留在全局范围之外 比如: function scriptloader() { this.grabscript

假设我有一个包含以下内容的文件“test.js”:

var test = 'something';
然后我有一个主脚本,需要加载test.js来获取测试变量

显然,这是可行的:

$.ajax({dataType: "script", cache: true, url: 'test.js'});
问题在于变量
test
存在于全局范围内。我很好奇是否有办法将其添加到对象中,并将其保留在全局范围之外

比如:

function scriptloader() {
    this.grabscript = function() {
        return $.ajax({dataType: "script", cache: true, url: 'test.js'});
    }
}

var myloader = new scriptloader();

myloader.grabscript();
理想情况下,myloader将包含加载的变量
test
。但是,我可以控制台.log(test)仍然可以看到“something”


有没有办法将加载的脚本锁定到作用域中,或者我是在做梦?

您可以使用
eval
实现此目的,并在本地作用域中创建一个具有预期名称的变量:

(function(jsString) {
    var test;
    eval(jsString);
    console.log(test); // 'something'
})("var test = 'something';");
console.log(test); // Exception: undefined variable
然后需要使用该自定义函数,而不是中使用的()

当然,对于每个全局变量,这并不是一个包罗万象的方法,对于类似的情况,您需要创建一个单独的全局对象(例如,使用
)来评估脚本


但是,使用JSONP可能比使用变量更好。

您可以尝试以下方法:

function scriptloader() {
  this.grabscript = function() {
    var loader = this;
    $.ajax('test.js', {
      complete: function(response) {
        var js = '(function() {' + response.responseText + ' loader.test = test; })();'
        eval(js);
      },
      dataType: 'text'
    });
  }
}

然后,
scriptloader
实例将获得一个名为
test

的属性。如果您对test.js没有控制权,并且必须接受将test声明为全局变量,解决方法是在页面内的iframe中加载test.js。这种方式测试将是一个全局变量,但仅在iframe窗口的范围内。从主页上,您可以通过
ifr.contentWindow.test

访问它。您可以尝试扩展页面上已存在的对象

假设你的页面上有这样一个脚本

var app = {
    loadedScripts
    ,loadPageScript : function(scriptUrl, cb) {
        $.getScript(scriptUrl, cb)
            .fail(function( jqxhr, settings, exception ) {
                console.log(exception);
        })
    }
}

app.loadPageScript('/test.js', function(){
    app.loadedScripts['test']();
});
您的test.js文件:

if(!app.loadedScripts.test){
    app.loadedScripts.test = function() {

        app.someVar = 1;

        app.someFunction = function(){
            console.log('iha');
        };
    }
}

有趣的问题。。。我能想到的在它自己的上下文中隔离已加载文件的唯一方法是通过iframe加载该文件,然后从父对象中提取对象,这实际上是一个有趣的想法……难道没有人会认为,如果发生了这样的情况,那么也许你应该重新考虑你的设计方法,比如
var test='something'是否有问题???似乎有一个比你的
test.js
脚本更好的地方,因为它在其他地方是需要的。你对test.js有控制权吗?这显然是一个简单的例子。实际上,它加载到一个脚本中,该脚本充当数据集的模型,因此我的问题是无法重新构造它(即,将其包含在对象中)。我刚刚意识到,@Justin在评论中已经提出了这个答案…除了当你运行$.ajax时,脚本会被加载,内容会进入全局范围。你的意思是因为$.ajax猜测响应是JS,并自动评估它?是的,这是个好机会。我编辑了我的回复以包含“类型”选项。这将阻止jQuery评估JS。至于我显式调用eval的地方,它被包装在一个闭包中,因此不应该设置全局变量。response.data应该是
response.responseText
。您可以放弃var js=。。。只需评估ResponseExt当然,这仅在没有跨来源限制的情况下有效:-/