开发者

can I load a javascript file under a context other than 'window'?

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


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.


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.


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.


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.


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"


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;
})();
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜