Pass data to encapsulated javascript code - javascript

in my webapp I have a variable like this
var data = {
getItem: function(key){
...
}
}
In all of my scripts I can use
data.getItem("Test");
But how can I use it in jquery plugins? Plugins often have following structure
(function($, window, document) {
//....plugin-code
});
How do I call this kind of structure? Is it possible to use my global data variable in such plugins?

If your data variable is global, then yes you can use it anywhere, including inside jQuery plugins.
You'll need to make sure that data is defined before any self-executing functions that are going to use it.

Actually they tend to have structure
(function($) {
// plugin-code
})(jQuery);
the points being that
they can assume that $ in this scope will always be jQuery, regardless of anything else loaded that defines $ e.g. prototype
everything is defined inside this closure and so only what you choose to expose (by $.fn or $.extend) is leaked out to the outside world
Obviously if it's just your plugin in your environment where you can assume you're always running $ = jQuery then you don't need these. (Yours also has document and window: I've never seen these overridden and I'm not sure what you'd pass in as arguments here other than document and window themselves?)
Were you asking about defining data inside the plugin or pulling it in from outside the plugin scope? There's no restrictions of what you can write inside, so if you define and use it inside then your code will work exactly as befoer. If you need to access data defined inside from the outside then you'll need to leak it out somehow, e.g. adding an accessor method to one of $, document or window.
If you're pulling in data from outside the plugin scope then you can still access global variables from inside your closure, or you could pass it in as an extra argument - I don't think it'd make any difference.

Related

How to detect JS frameworks/libraries used in a page?

I'd like to be able to detect all the frameworks/libraries used by a page, to help understand when content is dynamically-generated etc.
I downloaded and unpacked the source for two Chrome extensions, Library Detector and Appspector. It looks like they simply call window.FUNCTION_NAME_HERE, for example:
'Backbone.js': function () {
return window.Backbone && typeof(window.Backbone.sync) === 'function';
},
'Underscore.js': function () {
return window._ && typeof(window._.identity) === 'function' &&
window._.identity('abc') === 'abc';
},
'Spine': function () {
return window.Spine;
},
'Angular': function () {
return window.angular;
},
'Ning': function () {
return window.ning;
},
'Zepto': function () {
return window.Zepto;
}
etc.
I have a few questions:
What are the identifiers for each framework (e.g. "Spine", "angular") called? Is there any way to retrieve this information via AJAX or otherwise, so I don't have to manually enter them?
I don't really understand what window.angular means, besides that it returns either the angular object or None. I know that AngularJS has loaded if the angular function is accessible through the window object, but I'm not really sure what it even means to be a member function of the window.
Why is the procedure for Backbone and Underscore different than all the others? How do you know which one to use?
I tried running both extensions on the Uber homepage, which uses React, and neither of them detected React. When I tried to console.log(window), there wasn't a React object listed either. Why is this, and how can I still detect the framework in these cases?
It looks like you have misunderstood how that code detecting libraries work, and of course that relates to understanding the window object.
In a browser javascript environment window is the global object. All variables are defined as properties of the global window object, unless they are defined within a function with the var keyword.
Let's say you visit a page that uses jQuery library, open the browser console and type jQuery. That should respond with a function, which jQuery is. Essentially jQuery is a variable defined in the global scope, and it is available as a variable by it's name, and as a property of the window object: window.jQuery.
What libraries do by default if you include them with <script> tag is define themselves as a global variable. So with Backbone.js you will have Backbone global variable defined for you, and it will be available as window.Backbone, because window is the global object.
Similarly, Angular will define angular global variable, Zepto will define Zepto, and so on.
For this reason you should be able to detect any library by the global variables it defines.
A caveat however, is that in modern javascript applications, libraries do not necessarily register a global variable. They may be defined within a scope (a function) of that application. For this reason checking window.Libraryname doesn't guarantee the page isn't using this library. And in fact it may be a very difficult task to detect a library in this case.
There are too many frameworks/libraries, so it is up on you to create the list, or find anyone who maintains one. Then you would look into what global variables that framework defines, so you could look for them as the identifier of that framework.
As I explained above, angular is the global variable, also available as window.angular. If you create a scoped angular variable, like function (){ var angular = "my angular"; }, you will still be able to get the global one with window.angular.
It is possible that the maintainers of that code became aware of two or more libraries that define Backbone global variable. And only the Backbone we know about, includes the sync function. That might be the reason they additionally check that Backbone.sync is a function. They can't just check for the Backbone.sync function without checking for Backbone first, because on non-backbone pages that would cause error.
Similarly, with Underscore, there might be many libraries that define global _ variable, so we can know for sure it is the Underscore library by checking one of it's methods in work.
As I mentioned above, libraries will not necessarily define a global variable, in which case you will not be able to detect them automatically. As an example, in a modern javascript application, you could use a library as a dependency with Browserify, or RequireJS, in which case the library most likely will not register any global variables.

What is the correct way to wrap Angularjs code in a closure?

I have a simple application outlined in this question: Angular scope not affecting ng-show as expected
Which exposes my application via global variables, this is obviously not ideal.
I have tried wrapping the Angularjs code in a closure but I get errors in the browser telling me that the objects I am trying to access aren't accessable.
(function() {
// App code here
});
Is there a way to expose my app so with the current layout it functions correctly or do I need to change the whole struction of my app to achieve this.
I am ideally trying to reduce global variable pollution while keeping the app structure the same in both the html and js.
You are missing the call part.
Here is one format, there are a few others.
(function (a, b){
//Do stuff with `a` and `b`
})("a", "b");
Note the final pair of parens. Any parameter that you define, and later pass in are global within the scope.

Break the encapsulation of immediately executed anonymous functions?

A common Javascript pattern is:
(function() {
var localScopedValue = "foobar";
// code... functions...
}());
The self-executing or immediately executed anonymous function creates a scope for everything inside it to prevent pollution of the global scope, and it also theoretically prevents anyone from getting references to either the function object or anything defined inside it from an outside script, browser console, etc. That's the idea, anyway.
However, Javascript being a dynamic language with reflection, etc., I am wondering if there is any way -- no matter how hackish (but not editing any existing code) -- of getting references to locals that are not deliberately exposed from Javascript code.
Reason: pure curiosity / breaking things.
Adding: Things I'm looking at include Function.caller and event listeners, basically anything where items inside the IIFE are known to call/hook out, but I can't put together the complete package.
JS doesn't have "real" reflection - all it has is the ability to access the properties of an object using a variable as a key with myObject[myVar] syntax instead of myObject.myProperty.
This therefore provides no access to lexically scoped private variables.

Why wrap every prototype "class" object with an anonymous function in JS?

Looking at this JS code by David Fowler he wraps every "class" with an anonymous self executing method where he sends in jQuery and window. I get that this is a way for ensuring that $ and window are actually the global jQuery and winndow variables you'd expect them to be.
But isn't this a bit over-protective? Should you protect yourself from someone else changing the $ and window variable - is there actually code that does that, and if so why? Also, are there other advantages to wrapping everything like this?
If I remember correctly there are some other libraries than jQuery using the $.
The concept of using function context to create local / function scopes is all about to protect your own code. This especially makes sense if you expect your Javascript code to run in an environment where multiple other (maybe even unknown) scripts may get loaded.
So, if some other Javascript code which got load before your own, assigns window.$ with some other value (it might load the prototype framework for instance), then your code is already screwed if you try to access jQuery specific things.
Another point there is the "a--hole"-effect. Someone creates a line like
window.undefined = true;
...
Now, all your checks against undefined will pretty much fail. But by explicitly creating those variables/parameters and filling them with the values you expect, you can avoid all those problems.
(function(win, doc, $, undef) {
}(window, window.document, jQuery));
Generally most top-level JavaScript code should be wrapped in an IIFE, whether they pass in particular variables or not. This prevents variables created with var from polluting the global scope.
Another small benefit is minification: if you minify your code, making window into a "local variable" by passing it in as a parameter allows the minifier to rename it. This benefit goes away if you gzip, however, so it's not a real win.
Mostly people just pick a pattern for their IIFEs and stick with it, so in his case he's decided this is they way he writes his .js files and he does so uniformly. Having a uniform standard is valuable in and of itself.
To clarify, the code can be written in slightly longer form with
(function () {
var $ = jQuery;
var window = window;
// ...
}());
The code inside the anonymous function is the the function scope, so it prevent confliction with the global variables.
Imaging that if every jQuery plugin is not wrapped in a anonymous function, then there will be a global variables hell.
It's just to preserver integrity.
$ can be Prototype, so sending jQuery as argument will save your code if someone else add a library/variable which overwrite $.
About the second argument "window", I see it as a module you want to write on.

JQuery - getting all JS functions

Do you know of a way to use JQuery for getting JavaScript elements of a web page?
For example, getting all JavaScript function names that are used in page and so on.
Thank you!
Getting all the function names is something that jquery should not be needed for--it is more of a language issue.
You can get all of the functions and variables in the global scope by looking at the window object, since everything in the global scope in the browser is really a property of this object. However, this will contain all of the variables in the global scope, including ones there by default and not added by another script.
You can loop through all of the properties of the window object with a for...in loop. Here is an example:
for (var obj in window) {
// obj is just the name of each property
// do stuff with window[obj]
}
However, if this is not strictly necessary, you should really avoid it. It's possible, but I would think twice before doing this and would be very careful.
not entirely sure if this works but...
$("script").remove();
doesnt remove only functions but should remove all script elements completely.
EDIT
nvm thought i read you wanted to remove the functions

Categories

Resources