Accessing a function defined inside a function from the global scope? - javascript

Long story short, I have a long code that uses jQuery. Lots of files, functions, etc. A less than ideal amount of our users are having issues with our code because some addons, toolbars and the like they have installed breaks our JavaScript code because of jQuery gets included twice and nasty stuff like that.
I thought I could just
Include jQuery
Use $.noConflict
Then include the whole rest of my code between something like:
.
(function($) {
// All of my code goes here.
})(jQuery);
I haven't checked if this fixes our issues with those users, but it does work. The problem is, in one part of the site (image upload) we have an iframe that needs to call some of those functions defined in our big chunk of code. I've tried putting those functions out of this unnamed function call, but it uses, on itself, other functions which have to be there.
Any idea or workaround of how could I be able to access functions defined inside that function (shown above) from a code that's outside of it?
Thanks!

You cannot access a function context from the "outside world". Well, to be accorate you could do it in some older js engines which allowed for accessing .__parent__ attributes, but that is old'n'busted and no longer available.
However, you would need to either expose some functions within your closure, or you creating a namespace object where you write all of your logic in (which also has to be available in the parent context).
So I'd suggest something like
(function( $ ) {
function myFunc() {
// do stuff
}
function anotherFunc() {
}
window.myFunc = myFunc; // expose myFunc globally
}( jQuery ));
Maybe even better:
var myNameSpace = { };
(function( $ ) {
myNameSpace.myFunc = function() {
// do stuff
};
}( jQuery ));
// somewhere else
myNameSpace.myFunc();

It is not an ideal practice, but you can declare those functions in the global scope.
(function($) {
globalFunct = function (arg1, arg2) { // Don't use var keyword
...
};
})(jQuery);
It isn't ideal because you can run into naming collisions, much like you are observing with jQuery. Improve upon this approach by putting all of your globally-accessible methods in a "package." Choose a unique name for it. This will prevent collisions.
// Somewhere outside of your anonymous function, in the global scope
var myPackage = {};
(function($) {
myPackage.globalFunct = function (arg1, arg2) {
...
};
})(jQuery);
Then call that method by invoking myPackage.globalFunct().

Why are you wrapping your code in a call to the jQuery function object which you pass in to your self-executing anonymous function; are you meaning to create a jQuery object from all of your code?
In order to expose your code to the outside world, you need to assign your functions and objects to an object which is outside of the scope of your code, such as the window object.
For example, if you had created an object containing various methods and properties that you wanted to expose, you could do this:
//Your self-executing anonymous function
(function($)
{
//Object which contains various useful methods and properties
var useful = {...};
//Expose it to the outside world
window.Useful = useful;
})(jQuery);
EDIT: as others have noted, it is not an ideal solution as you will indeed run into naming collisions if you are not careful. Also, using an object external to your anonymous function as a namespacing object (as others have stated) is my preferred method

Yes, you can "export" the function from within a closure:
Yes, you can "export" the function from within a closure:
(function() {
function a() {
console.log("a");
}
function b() {
a();
console.log("b");
}
// make b globally available
window.b = b;
})();
b();

window.PARTY_CATS_jQuery = jQuery.noConflict(true);
(function($) {
$(function() {
// All of my code goes here.
});
})(COMPANY_NAME_jQuery);
Then just use PARTY_CATS_jQuery in your global functions
If you feel PARTY_CATS_ is not a unique enough name pick something safer like BABY_KILLER_jQuery

Related

What is the point of non self-invoking, anonymous, javascript functions?

I understand about self invoking anonymous functions like so:
(function () {
//...
})();
and that most of the time they are used for creating closures and abstracting variables in frameworks. However I've also seen sources in different sites that declare anonymous functions but they do not invoke them. I'm curious as to how those are used. Are they invoked when the script is loaded? Note that in the sources tab they don't look like .js files. Instead they have a name like so:
extensions::utils, or extensions::Event etc.
They look like they're part of some kind of framework/library? I'm not sure. For example the extensions::Event has this code inside:
(function($Object, $Function, privates, cls, superclass) {'use strict';
function Event() {
var privateObj = $Object.create(cls.prototype);
$Function.apply(cls, privateObj, arguments);
privateObj.wrapper = this;
privates(this).impl = privateObj;
};
if (superclass) {
Event.prototype = Object.create(superclass.prototype);
}
return Event;
}) //<-Self invocation missing.
As you can see this is just declared but not used. The only thing I can think of is that this anonymous function is actually assigned to a variable called Event and is part of the extensions object or something?
Since the only content these files have is the non self-invoking function the most probable explanation is that the whole content of the file gets evaled and executed by appending a () at the end. This way we can have access to anonymous functions without assigning them to a variable i.e: var reference = function () {} and still execute them when needed and not during their creation.
EDIT: These 'files' seem to be things used by google chrome. I found them in unrelated websites. Also I was unable to find them when I opened the same site from firefox.

The way of good scoping in JavaScript

I am not a really good JavaScript user but I can get things done with it. I am not proud of the code I have written in JavaScript, so I decided to change that. Here is my first step:
I am trying create my own library for a project and the below is the initial structure.
window.fooLib = {};
(function (foo) {
"use strict";
foo.doSomeStuff = function(param1) {
console.log(new AccommProperty(param1));
}
//some internal function
function AccommProperty(nameValue) {
var _self = this;
_self.name = nameValue;
}
}(fooLib));
I used immediately invoked function expression here to initialize my variable. In this case it is fooLib.
I am not sure if I should do some other things to make window.fooLib more safe. I mean it can be overridden by any other code which will run after my code if I understand JavaScript correctly.
What are your thoughts?
If you want to prevent overwriting your variables, you may use Object.defineProperty() with writable:false, configurable:false. In your case:
(function () {
"use strict";
var foo = {};
//some internal function
function AccommProperty(nameValue) {
var _self = this;
_self.name = nameValue;
}
foo.doSomeStuff = function(param1) {
console.log(new AccommProperty(param1));
}
Object.defineProperty(window, "foolib", {value:foo});
}());
Still, there is no good reason for that. It would need EcamScript 5.1 to work, and there are no shims around; maybe something with getters/setters to prevent overwriting with the = operator.
But also, there should be no need to make your library un-overwritable. Just don't use code on your site that overrides the lib. Or maybe someone even wants to overwrite your functions with another, better lib with the same interface?
If the question is about a library to be shared, with possible namespace conflicts to others, you may have a look at jQuery.noConflict.
Every JavaScript object can be overriden. This is the nature of JavaScript and it is impossible to change it. So you cannot make your code safe in that sense.
As for selfinvoked functions: you should use them when you want to have local variables but viisible to all your functions. So in your case AccommProperty is such variable. Defining doSomeStuff inside scope makes no difference unless doSomeStuff will use variables defined inside scope.
So when you want to hide variables from user and/or you need globals and you are affraid of name conflicts use selfinvoked functions.
I am not sure if I should do some other things to make window.fooLib more safe. I mean it can be overridden by any other code which will run after my code if I understand JavaScript correctly.
You could try making window.fooLib a local variable instead. Using closures and nested functions one can emulate a namespace where you can put all your data instead of putting it into the global scope or attaching it to window object:
(function() {
// all functions nested in foo() have access to fooLib.
fooLib = {}
fooLib.doSomeStuff = function(param1) {
console.log(param1);
console.log(fooLib);
}
//some internal function
function AccommProperty() {
console.log(fooLib);
}
}());
See Javascript Closures: Encapsulating Related Functionality for more details.

What's the difference between these two approaches to namespacing?

I've got the first file in my code directory as follows
myNamespace.js
var myNamespace = {};
Then my subsequent files can look as one of the two following ways.
first
(function (ns) {
ns.DoStuff = function(){
// do stuff
}
})(myNamespace);
second
myNamespace.DoStuff = function(){
//do stuff
}
So what is the difference between these two methods? Both seem to work for me. Is there a more generally accepted convention?
sorry, still new to javascript
Your first approach will not work. It would create DoStuff on the global object (most likely window). You would need to replace this with ns, after you did that, there is no difference between the two approaches.
The former will have the adventage that you might be able to closure all your application/file related stuff into that outer self-invoking closure function. So you won't clobber the global namespace.
(function (ns) {
var foo = 10,
bar = 42;
ns.DoStuff = function(){
console.log('foo is ', foo, ' and its not available globally');
}
})(myNamespace);
You have an error in your first one, you've used this where I'm pretty sure you meant ns:
ns.DoStuff = function() {
};
Leaving that aside, your first approach tends to be better because you've created a nice little scoping function for yourself, which allows you to have private data and functions available to all of the public methods you create on your namespace, without making them globals. E.g.:
(function(ns) {
function privateFunction() {
}
ns.DoStuff = function() {
privateFunction(); // <=== works fine
};
})(myNamespace);]
privateFunction(); // <=== doesn't work, because it's private
I like doing it that way partially because I have thing against anonymous functions, and so I wouldn't define DoStuff as above, but rather like this:
(function(ns) {
ns.DoStuff = Namespace$DoStuff;
function Namespace$DoStuff() {
}
})(myNamespace);
Now the function I've assigned to myNamespace.DoStuff has a proper name, which helps me out when I'm debugging my code. But that name doesn't pollute the global namespace, which helps me stay sane and avoid conflicts with other code.

Enclosing external jQuery script

I have an external JavaScript file that will be used on pages with lots of other scripts. My script involves a lot of jQuery that listens for events, and by design, I have many global vars declared. I've been reading best practice articles, and a lot is said about 'polluting the global namespace' and inadvertent script interaction.
What's the best way to enclose (encapsulate?) my JavaScript file so that:
I can still access some of the
variables outside of the enclosure
The jQuery event listeners will
function properly
I'm not at liberty to disclose the code, so even general responses are appreciated. Additionally, any other tips on making scripts less vulnerable to other scripts on the page are welcome.
I've found enclosure styles for regular JavaScript, but does the use of jQuery complicate this?
Generally what this boils down to is encapsulating your objects into a "namespace". I use quotes there because the term is not an official semantic in JavaScript, but rather one that is achieved through basic object encapsulation.
There are several ways to do this, and it ultimately comes down to personal preference.
One approach is to just use a basic JS object, and keep everything in it. The name of the object should be semantic and give the object some meaning, but otherwise it's purpose is to just wrap your own code and keep it out of the global namespace.
var SomeName = {
alpha: 1,
beta: {a: 1, b: 2},
gamma: function(){
SomeName.alpha += 1;
}
}
In this case, only SomeName is in the global namespace. The one downside to this approach is that everything inside the namespace is public, and you have to use the full namespace to reference an object, instead of using 'this' - e.g. in SomeName.gamma we have to use SomeName.alpha to reference the contents of alpha.
Another approach is to make your namespace a function with properties. The nice feature of this approach is you can create 'private' variable through closures. It also gives you access to closured functions and variables without full namespace referencing.
var SomeName = (function(){
var self = this;
var privateVar = 1;
var privateFunc = function() { };
this.publicVar = 2;
this.publicFunc = function(){
console.log(privateVar);
console.log(this.publicVar); // if called via SomeName.publicFunc
setTimeout(function(){
console.log(self.publicVar);
console.log(privateVar);
}, 1000);
};
}();
The other bonus of this approach is it lets you protect the global variables you want to use. For example, if you use jQuery, AND another library that creates a $ variable, you can always insure you are referencing jQuery when using $ by this approach:
var SomeName = (function($){
console.log($('div'));
})(jQuery);
One method is to namespace like this:
var MyNamespace = {
doSomething: function() {},
reactToEvent: function() {},
counter: 0
}
You will just have to refer to the functions or variable using the namespace: MyNamespace.reactToEvent. This works fine for separating what you would normally have in the window (where all the confrontation is).
You can wrap your code in an anonymous Javascript function and only return what you want to expose to the outside world. You will need to prefix var to your global variables so that they remain only in the scope of the anonymous function. Something like this:
var myStuff = (function() {
var globalVar1;
var globalVar2;
var privateVar1;
function myFunction() {
...
}
function myPrivateFunction() {
...
}
return {
var1: globalVar1,
var2: globalVar2,
myFunction: myFunction
};
})();
Now you can access myStuff.var1 and myStuff.myFunction().
Two ways to encapsulate or limit namespace pollution
1) Create one global var and stuff everything you need into it.
var g = {};
g.somevar = "val";
g.someothervar = "val2";
g.method1 = function()
{
// muck with somevar
g.somevar = "something else";
};
2) For inline scripts, consider limiting the scope of the functions called.
<script>
(
function(window)
{
// do stuff with g.somevar
if(g.somevar=="secret base")
g.docrazystuff();
}
)(); // call function(window) then allow function(window) to be GC'd as it's out of scope now
</script>
I just started using RequireJS and have now become obsessed with it.
It's basically a dependency management system in a modular JavaScript format. By doing so you can virtually eliminate attaching anything to the global namespace.
What's nice is that you only reference one script on your page require.js then tell it what script to run first. From there it is all magic...
Here's an example implementation script:
require([
//dependencies
'lib/jquery-1.6.1'
], function($) {
//You'll get access to jQuery locally rather than globally via $
});
Read through the RequireJS API and see if this is right for you. I'm writing all my scripts like this now. It's great because at the top of each script you know exactly what you dependencies are similar to server-side languages - Java or C#.
This is a common practice with jQuery plugins for the same reasons you mention:
;(function ($) {
/* ... your code comes here ... */
})(jQuery);
This is an immediate function. If you declare your "global" variables inside, they will be local to this closure (still "global" for the code you create inside). Your event listeners will work inside here too, and you will still be able to reach real global variables.

call a specific javascript function when multiple same name function are in memory

I need to call specific js function. The problem is many time runtime situation can come where another js file may contain same name function. But i need to be specific that which function i am suppose to call.
Function overloading is not my solution.
Thanks and regards,
Tanmay
you're going to have to do some reorganization of your resources and use namespacing where you can.
if you have a method named saySomething defined twice, you would move one of them to an object (whichever suits your needs better).
var myNS = new (function() {
this.saySomething = function() {
alert('hello!');
};
})();
and the other defintion can be moved into a different object or even left alone.
function saySomething() {
alert('derp!');
}
you can now call the saySomething method like
saySomething(); // derp!
myNS.saySomething(); // hello!
edit: since it was brought up in comments, this
var myNS = {
saySomething: function() {
alert('hello!');
}
};
is equivalent to the first code block, in simpler form (if i'm remembering correctly).
At least in firefox, when you have two functions with the same name, the second will overwrite the first one.
So, you can't call the first one.
Try it:
function a() {alert(1);}
function a() {alert(2);}
a(); // alerts '2'
See in jsfiddle.
In javascript, similarly named functions automatically override previous function defined with the exact same name.
Let's say your page includes 1.js and 2.js and both of them define the same function, for example say, display(). In this case, based on which js file is included the last, the definition of 'display()' in that file will override all other prior definitions.
I use function scope to limit the scope of variables and functions
Here is an example:
// existing function in JavaScript
function one() {
console.log('one');
}
one(); // outputs one
// inserting new JavaScript
(function() { // anonymous function wrapper
'use strict'; // ECMAScript-5
function one() {
console.log('two');
}
one(); // outputs two
})(); // end of anonymous function
one(); // outputs one
I hope that helps
:)

Categories

Resources