Javascript 在私有范围内包含JS文件

Javascript 在私有范围内包含JS文件,javascript,Javascript,我只是希望能够包含一个JS文件,但不希望在全局范围内对其进行评估 我浏览了labjs和requirejs,尽管它们可以做1000件其他事情,但它们似乎都不能解决这个问题 我知道我可以包装foo.js的代码,以便它需要特定的上下文,并且可以在中执行操作,但这不是我想要的(必须更改源文件)。相反,我希望源JS文件与任何其他JS文件一样,不需要任何元数据,也不需要通过包含文件本身的代码解析运行时执行上下文;在包含的文件之外,这是可以的 为清晰起见,提供了一些简单的演示: /* * Example 1

我只是希望能够包含一个JS文件,但不希望在全局范围内对其进行评估

我浏览了labjs和requirejs,尽管它们可以做1000件其他事情,但它们似乎都不能解决这个问题

我知道我可以包装
foo.js
的代码,以便它需要特定的上下文,并且可以在中执行操作,但这不是我想要的(必须更改源文件)。相反,我希望源JS文件与任何其他JS文件一样,不需要任何元数据,也不需要通过包含文件本身的代码解析运行时执行上下文;在包含的文件之外,这是可以的

为清晰起见,提供了一些简单的演示:

/*
 * Example 1 - apply to current context
 */
function x() {  
    include('foo.js'); // provides foo()
    foo(); // ok!
}
foo(); // not ok!


/*
 * Example 2 - apply to namespace context
 */
include.apply(ns, ['foo.js']); // provides foo()
ns.foo(); // ok!
foo(); // not ok!
我知道这可能是通过使用
eval()
或使用字符串创建
新函数来实现的,但我希望有更好的解决方案。

如果不依赖包含的源文件以符合某种模式,就没有干净的方法来实现(我可以考虑将每个文件注入到自己的iframe中,这样它们就可以使用自己的
窗口运行,但我认为这并不理想)

这并不一定意味着您无法实现所包含文件的解耦(如您所说,在不了解运行时上下文的情况下),但文件仍然需要表现良好

CommonJS模块系统(它)展示了实现这一点的一种方法。通过将代码包装在提供
导出
对象的函数中,并将所有(以前)全局属性分配给此对象,RequireJS可以返回此对象,供您分配给任何范围内的任何对象

例如:

function x() {  
    var foo = require('foo.js').foo; // provides foo()
    foo(); // ok!
}
foo(); // not ok!

var ns = require('foo.js');
ns.foo(); // ok!
foo(); // not ok!

是的,这需要编辑源文件,但它仍然提供了您想要的好处。

我认为除了您自己概述的方式之外,不可能这样做

一种解决方案是将代码封装在服务器端的函数中,编写一个include函数来加载js文件并用函数的名称空间进行响应

服务器端的包装代码

require.response('foo', function(exports) {

    // Content in foo.js
    exports.a = function() { return 'A'; }
    this.b = function() { return 'B'; }
    function c() { return 'c'); }

});
客户端js:

window['require'] = (function() {

    var list = {};
    function require(name, cb) {
        if (list[name]) {
            if (list[name].ns) {
                cb(list[name].ns);
            }
            else {
                list[name].cb.push(cb);
            }
        }
        else {
            list[name] = {cb: [cb]};

            // Code to load js file

        }
    }

    require.response = function(name, func) {
        var ns = {};
        list[name].ns = ns;
        func.call(ns);
        for(var i = 0, l = list[name].cb; i < l; i++) {
            list[name].cb[i](ns);
        }
    }

    return require;

}());

很遗憾,在结束这个老问题时,没有找到可接受的解决方案。一些好的建议,但都打破了我的要求。我想这可能是不可能的,因为语言的当前特性集。

使用iFrame来包含加载的javascript的范围

将脚本加载到页面后:

<script src = "path/to/clientside-require/src/index.js"></script>
请注意,由于浏览器不允许同步加载资源(由于用户体验差),因此使用javascript加载外部脚本的任何尝试都必然是异步的(因此使用承诺)

除非浏览器启用同步加载,否则这种格式将最接近我们所寻找的格式



作为额外的好处,脚本加载的
require()
功能可用于加载
html
css
json
,甚至
node\u模块
(只要模块能够使用
require()
).

Caja可能值得一看:+1个有趣的问题,我说使用eval。是的,如果使用不当,eval可能会很危险,但如果它完成了任务,并且你将其很好地使用……看起来这与第9框给出的答案基本相同,不是吗?我知道你同时给出了答案,所以我不想说你抄袭了him,但是在看过RequireJS文档之后,我相信node.js中的代码可能来自CommonJS项目?这可能是对的,但我不是回答这个问题的合适人选。自从我发布了这篇文章,我已经编写了上面脚本的更完整的实现。我可能会在未来的项目中使用一些东西。我可以如果感兴趣,请发布它?不,谢谢。我目前的解决方案基本上是已经发布的方案——将“包含”代码包装在一些特殊代码中。这个问题的目的是看看不这样做是否可以实现。无论如何,谢谢!
<script src = "path/to/clientside-require/src/index.js"></script>
/*
 * Example 1 - apply to current context
 */
require("foo.js")
  .then((foo)=>{
     foo(); // ok
  })
foo(); // not ok


/*
 * Example 2 - apply to namespace context
 */
var promise_foo_attached = require("foo.js")
  .then((foo)=>{
    window.ns.foo = foo; // provides foo to ns
  })

// then, as long as promise_foo_attached has resolved:
ns.foo(); // ok!
foo(); // not ok!