如何在同一页面上隔离不同的JavaScript库?

时间:2010-11-12 12:55:53

标签: javascript isolation

假设我们需要在第三方页面中嵌入小部件。例如,这个小部件可能使用jquery,因此widget携带一个jquery库。 假设第三方页面也使用jquery但使用不同的版本。 嵌入小部件时如何防止它们之间发生冲突? jquery.noConflict不是一个选项,因为它需要为页面中加载的第一个jquery库调用此方法,这意味着第三方网站应该调用它。这个想法是第三方网站不应该修改或做任何事情,除了将带有src的标记放到小部件中以便使用它。

此外,这不是jquery的问题 - 谷歌闭包库(甚至已编译)可能会作为一个例子。

除了明显的iframe之外,还有哪些解决方案来隔离不同的javascript库? 也许加载javascript为字符串然后eval(通过使用函数('代码到eval'),而不是eval('代码到eval'))它在匿名函数中可能会做到这一点?

5 个答案:

答案 0 :(得分:9)

实际上,我认为jQuery.noConflict正是您想要使用的。如果我正确理解了implementation,那么您的代码应如下所示:

(function () {
var my$;

// your copy of the minified jQuery source

my$ = jQuery.noConflict(true);
// your widget code, which should use my$ instead of $
}());

noConflict的调用会将全局jQuery$个对象恢复为以前的值。

答案 1 :(得分:4)

Function(...)在你的函数中创建一个eval,它没有任何好处。

为什么不使用iframe为第三方内容提供默认沙盒。

对于友好的用户,您可以在他们与您的网页之间共享文字数据,使用parent.postMessage代替现代浏览器,或者window.name hack for the olders。

答案 2 :(得分:2)

我建立了一个库来解决这个问题。我不确定它是否会对您有所帮助,因为代码仍然必须知道问题并首先使用库,所以只有在您能够更改代码以使用库时它才有用。

有问题的图书馆名为Packages JS,可以免费下载和使用,因为它是知识共享许可下的开源版。

它基本上是通过在函数内部打包代码来实现的。从这些函数中,您可以将要公开的对象导出到其他包。在使用者包中,您将这些对象导入本地命名空间。如果其他人或甚至您自己多次使用相同的名称并不重要,因为您可以解决歧义。

以下是一个例子:

(文件示例/ greeting.js)

Package("example.greeting", function() {
  // Create a function hello...
  function hello() {
    return "Hello world!";
  };

  // ...then export it for use by other packages
  Export(hello);

  // You need to supply a name for anonymous functions...
  Export("goodbye", function() {
    return "Goodbye cruel world!";
  });
});

(文件示例/ ambiguity.js)

Package("example.ambiguity", function() {
  // functions hello and goodbye are also in example.greeting, making it ambiguous which
  // one is intended when using the unqualified name.
  function hello() {
    return "Hello ambiguity!";
  };

  function goodbye() {
    return "Goodbye ambiguity!";
  };

  // export for use by other packages
  Export(hello);
  Export(goodbye);
});

(文件示例/ ambiguitytest.js)

Package("example.ambiguitytest", ["example.ambiguity", "example.greeting"], function(hello, log) {
  // Which hello did we get? The one from example.ambiguity or from example.greeting?
  log().info(hello());  
  // We will get the first one found, so the one from example.ambiguity in this case.

  // Use fully qualified names to resolve any ambiguities.
  var goodbye1 = Import("example.greeting.goodbye");
  var goodbye2 = Import("example.ambiguity.goodbye");
  log().info(goodbye1());
  log().info(goodbye2());
});

示例/ ambiguitytest.js使用两个库来导出函数再见,但它可以显式导入正确的函数并将它们分配给本地别名以消除歧义。

以这种方式使用jQuery意味着通过在调用Package和Exporting它现在公开给全局范围的对象中包装它的代码来“打包”jQuery。这意味着改变图书馆有点可能不是你想要的,但是如果没有诉诸iframe,我就无法看到。

我计划在下载中包含流行库的'打包'版本,jQuery肯定在列表中,但目前我只有一个打包版本的Sizzle,jQuery的选择器引擎。

答案 3 :(得分:0)

您可以在jQuery上调用Google API的完整网址,而不是寻找没有冲突的方法,以便它可以在应用程序中运行。

答案 4 :(得分:0)

<script src="myjquery.min.js"></script>
<script>window.myjQuery = window.jQuery.noConflict();</script>
...
<script src='...'></script> //another widget using an old versioned jquery
<script>
(function($){
    //...
    //now you can access your own jquery here, without conflict
})(window.myjQuery);
delete window.myjQuery;
</script>

最重要的一点:

  1. 在您自己的jquery和相关插件标签之后立即调用jQuery.noConflict()方法

  2. 将结果jquery存储到全局变量中,其名称几乎没有冲突或混淆的可能性

  3. 使用旧的版本化jquery加载小部件;

  4. 后续是您的逻辑代码。使用一个闭包来获得一个私人的$ for convience。私人$不会与其他jquerys冲突。

  5. 您最好不要忘记删除全局临时变量。