Unloading JS file loaded with Headjs - javascript

I have a page that could contain a different inner page at any specific time.
Each inner page needs a specific js file, that is being loaded dynamically using the Headjs.
To avoid collisions (of methods and object names), I would like to unload the old js file before loading a new one.
Does anyone know how to do it, or if it is even possible? Thanks!

No. Theoretically there's nothing like "unload" javascript file. Once its loaded its there all the time.
But there might be other tricks to avoid "collision", mainly clean code. some examples for your case would be
1- Usage of namespaces
2- avoid global variables
3- define everything within a scope and understand scopes
4- Use understandable descriptive variable names, avoid variables named s,i,j, etc.. unless you are used to that and know what're doing. Also be aware since javascript files are loaded when a page is requested, so it causes extra traffic to use huge large names for variables and classes.
Lets say you have functions with same name but live in different scopes/namespace
Example:
var myclass;
if (something) myclass = Obj1;
else if (somethingelse) myclass = Obj2;
myclass.func();
so here you go, two functions with the same name, but live in different classes.and so you can switch between different implementations
Hope this helps

Related

How to Unload and Garbage Collect Module in Client-side ES6 JavaScript?

I am writing a networked application that needs to load and unload self-contained (approved) code dynamically. The main goal, in short, is to load these scripts for short amounts of time and avoid global name collisions or contaminating the global scope, and being able to unload them and have everything be garbage collected.
The initial problem was that any global variables will persist after unload if I simply add and remove a script in the DOM.
My temporary solution was to wrap all of my individual dynamic code section files in:
systemArray.push((function() {
// local-global scope
function main() {
// do something
}
return main;
}()));
...
...
// some external code calls:
systemArray[sandboxIdx](); // max of 10 sandboxes at once, need to unload old sandboxes that have been exited
and simply pop the array upon unload to let the garbage collector do its work. However, this doesn't really allow for splitting the sub-program into multiple files, and it seems a little error-prone unless I can do some preprocessing on the server-side to create a concatenated file.
Then I looked into ES6 modules. These seem to be fine and avoid name collisions, but it's unclear to me whether modules can ever be unloaded, which is the key thing that I need to do without changing webpages or refreshing.
Firstly, is there a way to unload a module explicitly at runtime? The main, non-unloading part of the application only needs to import one function, but the scripts themselves may have a lot of code.
Secondly, if the answer is yes, do any modules that the unloaded module load also get unloaded? Are global variables within the modules correctly garbage collected? If the answer is no, what other options are there?

Modify javascript to expose a function-scoped variable

I would like to be able to expose a function-scoped variable that is part of a website's (not mine) javascript.
Here's a simplified example:
function addHooks(e, t, n, i) {
var props = { // Would like to expose this
update: function() { ... },
remove: function() { ... },
find: function() { ... },
};
...
}
In the above example, I would like to expose the props variable so that my webextension can then access this to modify the behavior of the website. Please note, that the website that serves this JS file isn't under my control and thus, I cannot simply modify the source file to export this variable. However, I'm fully open to modifying the final code that the browser runs (I just don't know how to). The javascript file containing the addHooks function appears to be added dynamically via XHR.
Although I have no idea on how to accomplish this programmatically, I have had some success setting a breakpoint and then issuing window.siteController = props in the browser's developer console. Unfortunately, manual user-intervention is not something I can package and distribute.
One method that I have been toying with is the idea of making an AJAX request for the JS file, modifying its script contents and appending it to the page.
Is there a canonical, programmatic way in which a function-scoped variable can be exposed?
if it's the props object variable that you want exposed, you could return he entire object from the functin, like in closures.
Or , you could, simple declare a the enclosing function as a constructor function, set props as this.props and then, invoke the same function elsewhere, using the new keyword.
Let me know if this helps
EDIT:
Thanks to Makyen who pointed out my error.
Apparently you might be able to do it if you re-define the function in a page script and insert it as a script element. (See the comment for two references).
Just be sure that your <script> element is inserted after the original definition and then you can either return props at the end of the function, or use this.props and use the function either as a constructor or using thecallfunction, passing an object that will get the props property added.
Old answer ( __ wrong__ apparently)
Short answer: you can't.
Full explanation: if you can't change the code of the function and you can only use the function (call it) you cannot alter its variable's scope (and good thing you can't, too. There's a reason why the variable was limited to its current scope).
And you can't change the website's JavaScript. As a Firefox or Chrome extension (and possibly the same fires to other browsers I'm not sure) you can't even access the function (let alone it's inner variables). I mean to say you can't even call it from the extension of it's in the website's code.
content scripts cannot see JavaScript variables defined by page scripts
More info and source
Firefox/Chrome runs your JavaScript code in a parallel environment, isolated from the website's environment. This is of course for security reasons. It also helps for you to be able to develop without knowing the exact inner workings of each website your code might be injected into, as you don't need to bother regarding naming conflicts (which would be impossible if it weren't for the separation environments).
The only thing you do have access to is the DOM, through which you can gather information, alter the website and even talk with the website in some cases (the website should follow a protocol you decide upon as well).

JavaScript Usage - OOP, Prototypes, and (not-so) Simple Variables

I have been programming JavaScript for a fair while. I haven't ever taken a course or read guides/books as to best practices, but I've seemed to figure things out pretty well as I've gone. I know that my code isn't always the shortest and cleanest, but it's made sense for me.
I recently got into object-oriented programming and think that it's a great time to jump head-first into the language. While I know that it would be in my best interest to spend a few days pouring over OOP, I have a specific question that would help me in my attempts.
Making Variables Objects
I have a PhoneGap application, for example, that includes many functions each serially listed in split-up .js files. Everything worked okay, but I would have to keep passing the same few functions between every function, and the potential for error was fine. After reading into methods and objects a little, each page evolved to this usage:
var myPage = {
myVar1 : 'value',
myVar2 : 32,
initialize : function() {
//code that initialized the variables within this object
},
doSomething : function() {
//function that would do something with myPage vars
}
//...
};
Using this methodology, each page ended up as a grand variable with many encompassed methods and variables. This cleaned up quite a bit and greatly reduced global vars, but I still don't feel as though it's perfect. My shared .js files are broken into types and many objects, each with their own functions. My first question is: is this a bad thing, and if so, why? If I could get an explanation for my specific use, it would benefit me much more than seeing optimal examples in textbooks and guides.
Making Prototypes and Classes with a Single Instance
Looking at examples provided here and across the web and dead-tree publications, I see that objects and prototypical behavior is defined as a class, then instances of the class are created. Nothing that I need to do, however, seems to fit this budget, and I'm nearly positive that it's because I'm simply not thinking in the correct paradigm. However, if I have a function that validates input, how does that fit into a better OOP methodology?
I simply have a variable/object named validate that contains the functions necessary, then put that variable in the shared file. If I were to create it as a class and create an instance of it each time that I needed to validate something, doesn't that create a lot more overhead? I don't see how it works for applications such as this.
I think that OOP is the way to go, and I want to be part of it. Thanks in advance for all answers and comments.
My first question is: is this a bad thing, and if so, why?
Competent developers avoid having functions defined in the global scope (what you do when you write function() {} inside a script) because it pollutes the global scope, where many other scripts try to do the same. Think of it as many of us trying to make a better "share()" function on the same page - only one of us will win.
I see that objects and prototypical behavior is defined as a class, then instances of the class are created. Nothing that I need to do, however, seems to fit this budget, and I'm nearly positive that it's because I'm simply not thinking in the correct paradigm
There's not much you can do there. If you have a function that validates input, then it would be better as part of the element:
someElement.validate(); // as a prototype
instead of the conventional
validate(someElement); // as a global function

Why is it bad to make elements global variables in Javascript?

I've heard that it's not a good idea to make elements global in JavaScript. I don't understand why. Is it something IE can't handle?
For example:
div = getElementById('topbar');
I don't think that's an implementation issue, but more a good vs bad practice issue. Usually global * is bad practice and should be avoided (global variables and so on) since you never really know how the scope of the project will evolve and how your file will be included.
I'm not a big JS freak so I won't be able to give you the specifics on exactly why JS events are bad but Christian Heilmann talks about JS best practices here, you could take a look. Also try googling "JS best practices"
Edit: Wikipedia about global variables, that could also apply to your problem :
[global variables] are usually
considered bad practice precisely
because of their nonlocality: a global
variable can potentially be modified
from anywhere, (unless they reside in
protected memory) and any part of the
program may depend on it. A global
variable therefore has an unlimited
potential for creating mutual
dependencies, and adding mutual
dependencies increases complexity. See
Action at a distance. However, in a
few cases, global variables can be
suitable for use. For example, they
can be used to avoid having to pass
frequently-used variables continuously
throughout several functions.
via http://en.wikipedia.org/wiki/Global_variable
Is it something IE can't handle?
No it is not an IE thing. You can never assume that your code will be the only script used in the document. So it is important that you make sure your code does not have global function or variable names that other scripts can override.
Refer to Play Well With Others for examples.
I assume by "events" you mean the event-handling JavaScript (functions).
In general, it's bad to use more than one global variable in JS. (It's impossible not to use at least one if you're storing any data for future use.) That's because it runs into the same problem as all namespacing tries to solve - what if you wrote a method doSomething() and someone else wrote a method called doSomething()?
The best way to get around this is to make a global variable that is an object to hold all of your data and functions. For example:
var MyStuff = {};
MyStuff.counter = 0;
MyStuff.eventHandler = function() { ... };
MyStuff.doSomething = function() { ... };
// Later, when you want to call doSomething()...
MyStuff.doSomething();
This way, you're minimally polluting the global namespace; you only need worry that someone else uses your global variable.
Of course, none of this is a problem if your code will never play with anyone else's... but this sort of thinking will bite you in the ass later if you ever do end up using someone else's code. As long as everyone plays nice in terms of JS global names, all code can get along.
There shouldn't be any problem using global variables in your code as long as you are wrapping them inside a uniqe namespase/object (to avoid collision with scripts that are not yours)
the main adventage of using global variable in javascript derives from the fact that javascript is not a strong type language. there for, if you pass somes complex objects as arguments to a function, you will probebly lose all the intellisence for those objects (inside the function scope.)
while using global objects insteads, will preserve that intellisence.
I personally find that very usfull and it certainly have place in my code.
(of course, one should alwayse make the right balance between locales and globals variables)

How to avoid name clashes in JavaScript widgets

I have a JavaScript widget (a piece of embedded JS and HTML code) that's embedded on other sites. What should I do to make sure it's variable names don't clash with the hosting page variables?
I'd like this widget to be "inlined" meaning on the same page as the hosting page, not in an iframe, what's the best way to avoid name clashes with the hosting page or clashes with other widgets?
Name clashes can happen in several ways:
JavaScript variable names
JavaScript function names
DOM elements identifiers
CSS class names
maybe more...
I can think of several ways to avoid name clashes, but I was wondering if there's a best-practice or other general recommendations.
So here's my 2c:
Just use long and try-to-be-unique names. That's ugly and not full-proof, but is simple in concept.
Use an iframe. But as mentioned, I don't want to use an iframe for several reasons. I want the widget to inherit style attributes from the page (such as default font and background color) and most importantly, I don't know how large the widget is going to be. It depends on real-time data and may be of any size.
Use anonymous functions for better scoping, e.g. (function(){my code here})(). This solution, while elegant, still does not work for me b/c first, it only solves the JS name clashed but not the DOM ID ones or CSS class names and second, I also use jsonp for which I need to provide a callback function name, which eventually needs to be in the global scope, so it cannot be nested in the anonymous function scope.
Create a namespace mechanism in JavaScript that'll provide uniqueness of JS variables and function. Something of the style window['my_app'][variable_name] or window['my_app']function_name. That's a bit ugly as well, but at least I have control over the namespace and can generate guaranteed to be unique namespaces.
Javascript namespaces:
http://www.codeproject.com/KB/scripting/jsnamespaces.aspx
It is heavily used in several javascript frameworks/libraries, such as YUI:
http://developer.yahoo.com/yui/yahoo/
In my previous project I had a widget that was embedded on other sites, and to prevent name conflicts I prefixed all names that would be used in the embedding sites with a two letter prefix (I got the idea from Objective C, where all classes start with a prefix like NS...).
Of course I also used namespaces (e.g. var Foo = { bar: function() { ... }}) and "classes" (using John Resig's class implementation), because I use them regardless if I have a widget or not, but the names of the namespaces, classes and global variables or functions were prefixed - e.g. HMWidget, HMClass, hmDoSomething(), etc.
Regarding DOM IDs and CSS classes - first, I had to get rid of most IDs because of the possibility of having multiple widgets from my service on the same site. So the only IDs that were left were something like "widget_12345" to tell the widgets apart. The rest of the elements were identified by CSS classes, and all CSS declarations were done in relation to the main widget container (e.g. ".my_widget .left_column" instead of just ".left_column").

Categories

Resources