我可以在“窗口”以外的上下文中加载 JavaScript 文件吗?

发布于 2024-10-01 06:49:10 字数 1151 浏览 12 评论 0原文

我尝试加载一些外部 .js 文件,并遇到一些无法解决的命名空间冲突。

我的想法是以某种方式在自己的上下文中加载一些文件,将指向窗口对象的“this”替换为某个自定义名称空间。

例如:

first.js:

name = "first";

second.js:

name = "second";

在我看来,这种技巧非常有用。有可能吗?

编辑
似乎替换“this”并不能解决问题,因为它不是 javascript 中标识符解析的默认上下文。这是我的测试代码:

var first = {};
var second = {};

(function(){name = "first";}).call(first);
(function(){name = "second";}).call(second);


document.write('name= '+name+' <br/>\n'); //prints "second"
document.write('first.name= '+first.name+' <br/>\n'); //prints "undefined"
document.write('second.name= '+second.name+' <br/>\n'); //prints "undefined

有什么想法吗?

解决方案
这是不可能的。结果我比今天早上更聪明,所以我放弃了。 我向任何有类似问题并可能想要解决这个问题的人推荐这些具有启发性的阅读材料: http://jibbering.com/faq/notes/closures/
http://softwareas.com/cross-domain-communication-with-iframes

I try to load some external .js files, and have some irresolvable namespace conflicts.

I had the idea of loading some of the files in their own context somehow, replacing the "this" from pointing at the window object to some custom namespace.

example:

first.js:

name = "first";

second.js:

name = "second";

It seems to me that this kind of trick can be very useful. Is it possible at all?

EDIT
seems that replacing "this" does not begin to solve the problem, as it is not the default context for identifier resolution in javascript. this is my test code:

var first = {};
var second = {};

(function(){name = "first";}).call(first);
(function(){name = "second";}).call(second);


document.write('name= '+name+' <br/>\n'); //prints "second"
document.write('first.name= '+first.name+' <br/>\n'); //prints "undefined"
document.write('second.name= '+second.name+' <br/>\n'); //prints "undefined

any ideas?

RESOLUTION
It is not possible. I ended up wiser than I was this morning, and I gave it up.
I recommend these enlightening reading materials for anyone with a similar problem that might want to take a crack at it:
http://jibbering.com/faq/notes/closures/
http://softwareas.com/cross-domain-communication-with-iframes

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

向地狱狂奔 2024-10-08 06:49:10

我的一个想法是,在不需要修改外部 JavaScript 文件的情况下,以 AJAXy 方式获取 JavaScript 文件的内容(取决于你如何做到这一点),然后使用 new Function(code) 方式,然后用 new 初始化它:

surrogateWindow = new new Function(jsCode)();

那么 surrogateWindow 就是该代码的 this 。我认为这个想法应该可行。

One idea I've had for doing it without needing modifications to your external JavaScript file is getting the contents of the JavaScript file in an AJAXy way (up to you how you do that) and then put it all in a function using the new Function(code) way, then initialise that with new:

surrogateWindow = new new Function(jsCode)();

Then surrogateWindow is the this of that code. I think that that idea should work.

倾城°AllureLove 2024-10-08 06:49:10

我不清楚你这样做的原因;你到底用 this 做什么?

将 secondary.js 的内容包装在匿名函数中将防止该文件中的变量与全局变量发生冲突。如果您确实必须将 this 设置为非全局对象的特定对象,那么您可以执行类似

var differentThis = {};
(function() {
    // Contents of second.js go here
}).call(differentThis);

UPDATE

的操作,但您无法执行您想要的操作。您似乎想要访问 Variable 对象,它是在 JavaScript 中声明变量时添加属性的对象。在全局代码中,Variable对象是全局对象,因此可以访问它;在函数中,这是执行上下文的一个属性,无法直接访问。

I'm not clear on your reason for doing this; what are you using this for, exactly?

Wrapping the contents of your second.js in an anonymous function will prevent variables in that file from conflicting with global variables. If you really must have a this set to a particular object that isn't the global object, you could do something like

var differentThis = {};
(function() {
    // Contents of second.js go here
}).call(differentThis);

UPDATE

You can't do what you want. You seem to want to access the Variable object, which is the object to which a property is added when you declare a variable in JavaScript. In global code, the Variable object is the global object, so you can access it; within a function this is a property of the execution context that there is no way to access directly.

情魔剑神 2024-10-08 06:49:10

尽管这是一个老问题,但这个答案可能仍然与某些人相关:

加载 js 文件时,它会自动获取窗口的上下文。这是不可能改变的。
但是,如果您试图避免正在加载的库之间发生冲突,并且您无法控制这些库,并且它们没有内置的“无冲突”机制,那么有一个不错的技巧-
您可以将它们加载到无源 iframe 中。
这将使它们的上下文成为 iframe 的窗口,并且您仍然可以访问 iframe,因为这里不存在跨域问题。

您可以查看此库作为使用此技术的示例。

Even though this is an old question, this answer may still be relevant for some:

When a js file is loaded it automatically gets the window's context. That is not possible to change.
However, if you are trying to avoid conflicts between libraries that you are loading, and you don't have control over those libs, and they don't have a built-in "no-conflict" mechanism, then there is a nice trick -
you can load those into a source-less iframe.
This will make their context to be the window of the iframe, and you will still be able to access the iframe since there is no cross-domain issue here.

You can see this library as an example for use of this technique.

遇见了你 2024-10-08 06:49:10

您可以在 iframe 中加载文件,该文件不是 .js 而是 HTML 文件,例如:

<html>
<body>
  <script>
    var $ = parent.$, // you can share objects with the parent, eg: jQuery
      localObject = { // your local object definition
        name: 'first',
        showName: function(){
          $('div.name').html( this.name );
        }
      };
    //assign the local object to the custom namespace
    parent.customNamespace.object1 = localObject; 
  </script>
</body>
</html>

技巧是使用 parent. > 获取父页面中可用的 javascript 对象。

You can load your file in an iframe, the file is not a .js but an HTML file, like:

<html>
<body>
  <script>
    var $ = parent.$, // you can share objects with the parent, eg: jQuery
      localObject = { // your local object definition
        name: 'first',
        showName: function(){
          $('div.name').html( this.name );
        }
      };
    //assign the local object to the custom namespace
    parent.customNamespace.object1 = localObject; 
  </script>
</body>
</html>

The trick is to use parent. to get the javascript objects available in the parent page.

心奴独伤 2024-10-08 06:49:10

对于您编写的代码,我认为您误解了 JavaScript 中类的一些工作方式。在 Java 中,您可以删除 this.,但在 JavaScript 中则不能。您始终需要有 this. 。那么你的代码就变成了:

var first = {};
var second = {};

(function(){this.name = "first";}).call(first);
(function(){this.name = "second";}).call(second);


document.write('name= '+name+' <br/>\n'); //prints "undefined"
document.write('first.name= '+first.name+' <br/>\n'); //prints "first"
document.write('second.name= '+second.name+' <br/>\n'); //prints "second"

以更正常的类方式来完成它也很好。我不确定你的具体情况是什么,因为我看不到你的所有代码,所以你可能已经在这样做了。

function Something(name) {
    this.name = name;
}

var first = new Something("first");
var second = new Something("second");

document.write('name= '+name+' <br/>\n'); //prints "undefined"
document.write('first.name= '+first.name+' <br/>\n'); //prints "first"
document.write('second.name= '+second.name+' <br/>\n'); //prints "second"

For the code you've written, I think you're misunderstanding some of the way classes work in JavaScript. In Java you can drop the this., but in JavaScript you can't. You'll always need to have this. there. So then your code becomes:

var first = {};
var second = {};

(function(){this.name = "first";}).call(first);
(function(){this.name = "second";}).call(second);


document.write('name= '+name+' <br/>\n'); //prints "undefined"
document.write('first.name= '+first.name+' <br/>\n'); //prints "first"
document.write('second.name= '+second.name+' <br/>\n'); //prints "second"

It would also be good to do it in a more normal class way. I'm not sure exactly what your situation is as I can't see all your code so you might be already doing it this way.

function Something(name) {
    this.name = name;
}

var first = new Something("first");
var second = new Something("second");

document.write('name= '+name+' <br/>\n'); //prints "undefined"
document.write('first.name= '+first.name+' <br/>\n'); //prints "first"
document.write('second.name= '+second.name+' <br/>\n'); //prints "second"
笑忘罢 2024-10-08 06:49:10

好吧,你可以用这样的东西包装 js 文件的内容:

var externalInterfaceForYourObject = (function(){
  //code that defines your object

  //this should refer to the current anonymous function, and not the window object
  return this;
})();

Well you could wrap the contents of the js files with something like this:

var externalInterfaceForYourObject = (function(){
  //code that defines your object

  //this should refer to the current anonymous function, and not the window object
  return this;
})();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文