Is setting properties on the Window object considered bad practice? - javascript

I'm writing a quite complex JavaScript application that has an MVC architecture that I'm implementing using Prototype's Class support and the Module pattern. The application uses AJAX and the Observer pattern. I create my controller instance when the DOM has loaded, pass it a view and some models created from JSON data and away it goes.
However, I've found that I have to set my controller instance as a property on the Window object—i.e. declare it without using var—because I have an AJAX success callback that refreshes the view object owned by the controller and at this point in the code my nice little MVC world is not in scope.
I investigated passing in the view object as a parameter to the function containing the AJAX code, but this got really messy and would have led to some horrible violations of the MVC pattern, such as coupling the model and the view. It was horrendous.
Is doing things like storing my controller instance directly on Window considered bad form? It smells a bit like using a global variable to me, but I can't see any way around it.

Setting properties on the window object is equivalent to creating global variables. That is, sometimes doing it is inevitable, but you should try to keep it to a bare minimum, as it ends up polluting the global namespace.
In your case, creating a single property is not so bad. If you want to be extra careful about it, you can explicitly create a namespace for any stuff you need global access to:
// In init:
var mynamespace = {};
. . .
// Once the controller is available:
var namespace = window.mynamespace;
namespace.controller = controller;
namespace.foo = bar; // Set other stuff here as well.

I would say it's bad practice. You can always, and easily, create a namespace for your application and put globals in there, if you must.

They are useful when you want to call a global function whose name is not known beforehand.
var funcName = "updateAns" + ansNum;
window[funcName]();
They can be used to
a) avoid evil evals in most cases.
b) avoid reference errors to global variables.
x = x + 1 will generate a reference error if a global x is not defined.
window.x = window.x + 1 will not

Related

The confusion about Global object in JavaScript

I am beginner at JavaScript and I am trying to understand the Global window object in JavaScript. So, is it ok if I just imagine that any code that I write in the console like var text = "Hello"; console.log(text) is put inside window object like this Window{var text = "Hello"; console.log(this.text)} with this referencing window object. Is it ok if I consider it like that or it is not correct? Thank you
Is not pretty safe to make assumptions about the global object or the default this context, as it can vary from one javascript runtime to another, and some features like the strict mode also change this behavior.
Keep in mind that javascript not only runs in the browser -and global in node.js for instance does not work as in the browser-, and that there are a lot of different browser implementations out there.
Also, while var does write to global by default in some environments, const and let doesn't.
In node, functions called freely with no previous reference won't call them from global, but will fail instead. This heavily affects also front-end code since much of javascript for the browser nowadays is pre-compiled in a node environment via webpack etc.
So, succintly: is usually difficult to assume things about global, window and default this bindings and get them right. It is probably safer to assume that you don't have a default global object available and always refer window explicitly, as:
config.js
window.config = {foo: 'bar'}
window.someGlobalFunction = function() {...}
user.js
// do:
const elen = new User(window.config);
window.someGlobalFunction();
// don't
const elen = new User(config);
someGlobalFunction();
"is it ok to use the global object?"
Of course it is. If you know about the pitfalls and use the global object by purpose and not by accident.
(function() {
name = 12; // Note: This *is* a global variable
console.log(typeof name); // string. WTF
})();
The pitfalls are:
1) All undeclared (!) variables, and global variables declared with var automatically get part of the global object. That is bad, as that happens without any good reason, so you should avoid that (use strict mode, and let and const).
2) All scripts you run do have the same global object, so properties can collide. Thats what happens in the example above, name collides with the global window.name getter / setter pair that casts the number to a string. So if you set properties in the global object, make sure that the name is only used by you, and not by others (the browser, libraries, other codepieces you wrote ...)
If you know about these pitfalls and avoid them, you can and should use the global object by purpose, if, and only if, you plan to share a certain function / variable between different scripts on the page, so if it should really be globally accessible.
let private = 1;
window.shared = 2;
Yes, any function or variable can be accessed from the window object example:
var foo = "foobar";
foo === window.foo; // Returns: true
function greeting() {
console.log("Hi!");
}
window.greeting(); // It is the same as the normal invoking: greeting();

Angular - Should I use local variable or this.variable

I was looking for this but could not find a question as simple as I want it. The problem is really simple: In angular js, should I use local variables, or properties of this (in cases when I don't need to use this).
Example:
// I need "this" here because I need this collection in template
this.collection = SomeService.fetchCollection();
// I can use either "foo" or "this.foo" here, which one is better?
this.fetchSomeData = function(type) {
var foo = AnotherService.foo(type);
return FooService.call(foo);
}
A local variable, so it can be cleaned up as soon as the method exits. Otherwise it would stay unused in the parent's namespace.
But in 99% of cases that will have no real-world effect, so it doesn't matter.
Because you haven't declared 'foo' as a var it will be a global here, which is bad. You should at least prefix it with 'var' so it's scoped to the function and not globally; it shouldn't be available outside the function.
in my opinion it is a good practice not to reveal everything and keep it encapsulated - for example, it avoids moving logic to view which is bad
also, consider that you have a for loop iteration over i variable - would you also use this.i for such purpose?

JavaScript Closures use global setting object or pass it to each function

another question concerning javascricpt closures. I have a global "settings object". Is it better to use it from within functions in global scope or pass the object every time a function needs to access the object?
For a better understanding a little mockup of the situation here
Please ignore that "baz()" also gets the passed object within "foobar()" from the global scope within the closure. You see that both versions work fine.
The thing is that I am passing whatever object the function needs to work to every function and EVERY time (unneccesary overhead?), which might be nice and easy to read/understand but I am seriously thinking about changing this. Disadvantage would be that I have to keep the "this" scope wherever it gets deeper right?
Thanks for your advice!
Your settings object isn't global, it's defined within a closure.
As the intent is that it be accessed by other function within the closure, I'd say you were 100% fine to just access that object directly and not pass it as a parameter.
FWIW, even if you did pass it as a parameter the overhead is negligible because only a reference to the object is passed, not a copy of the whole object.
So you have basically three options:
You want to expose settings as a global variable, and have it accessed by your functions,
You want to hide settings as an implementation detail and have it accessed by your functions,
You want to give a possibility to supply different settings objects to different functions.
Global variable approach
Well, I guess it's a little bit like with any global variable. If settings is a singleton (for example it describes your application) and you can't see any benefit in having a possibility to call the same function with different settings objects, then I don't see why it couldn't be a global variable.
That said, because of all the naming conflicts, in Javascript it's good to "namespace" all the global variables. So instead of global variables foo and bar you should rather have one global variable MyGlobalNamespace which is an objects having attributes: MyGlobalNamespace.foo and MyGlobalNamespace.bar.
Private variable approach
Having a private variable accessed by a closure is a good pattern for hiding implementation details. If the settings object is something you don't want to expose as an API, this is probably the right choice.
Additional function parameter approach
Basically if you see a gain in having a possibility of supplying different settings to different function calls. Or perhaps if you can picture such gain in the future. Obvious choice if you have many instances of settings in your application.
EDIT
As to the question from the comments:
Example 1)
var blah = 123;
function fizbuzz() {
console.log(blah); // <-- This is an example of a closure accessing
// a variable
console.log(this.blah); // <-- Most likely makes no sense. It might work,
// because by default this will be set to a global
// object named window, but this is probably not
// what you want. In other situations this might
// point to another object.
}
Example 2)
var obj = {
blah: 123,
fizbuzz: function() {
console.log(this.blah); // <-- This is *NOT* an example of a closure
// accessing a private variable. It's rather the
// closest Javascript can get to accessing an
// instance variable by a method, though this
// terminology shouldn't be used.
console.log(blah); // <-- This MAKES NO SENSE, there is no variable blah
// accessible from here.
}
};
In a nutshell, I'd encourage you to read some good book on the fundamental concepts of Javascript. It has its paculiarities and it's good to know them.

Accessing variables from another CoffeeScript file?

What is best practice to get a variable outside of its anonymous function without polluting the global namespace?
A number of possibilities:
Create a properly name-scoped public accessor function to obtain the value upon demand.
Pass the value to the functions where it will be needed
Pass a private accessor function to the other module
Put the variable in a properly name-scoped global
Pass a "data object" to the other module that has the value in it (along with other values)
Which makes the most sense depends upon how much data you need to share, how widely it needs to be shared, whether the sharing is both ways, etc...
The typical design pattern for exposing global data with the minimum impact on polluting the global namespace is to do something like this:
var JF = JF || {}; // create single global object (if it doesn't already exist)
JF.getMyData = function() {return(xxx);}; // define accessor function
JF.myPublicData = ...;
Then, anywhere in your app, you can call JF.getMyData(); or access JF.myPublicData.
The idea here is that all public methods (or even data objects) can be hung off the JF object so there's only one new item in the global space. Everything else is inside that one object.
There have been several CoffeeScript questions along these lines:
How do I define global variables in CoffeeScript?
Expose a javascript api with coffeescript
Getting rid of CoffeeScript's closure wrapper
as well as several others that are environment-specific. If you posted a more detailed question with a concrete example, I could provide a more specific answer.

Help understanding twitters widget.js file, a closure within a closure?

http://a2.twimg.com/a/1302724321/javascripts/widgets/widget.js?1302801865
It is setup like this at a high level:
public namespace:
TWTR = window.TWTR || {};
Then a closure:
(function() {
...
})(); // #end application closure
Within the application closure:
TWTR.Widget = function(opts) {
this.init(opts);
};
(function() {
// Internal Namespace.
var twttr = {};
})();
Some methods are marked public, others private, and the only difference seems to be the naming convention (private starts with underscore '_').
Is it designed using the module pattern?
Why or what benefit do you get with a closure within a closure?
Since they load the widget.js before jquery, this means widget is designed to run w/o jquery since order matters correct?
Just trying to learn from this thing!
It is setup like this at a high level:
public namespace:
TWTR = window.TWTR || {};
That is bad coding practice, variables should always be declared with var. And there are no "namespaces" in javascript, that term is applied to the above construct but it isn't really appropriate. Better to say its methods are contained by an object.
Then a closure:
> (function() { ...
>
> })(); // #end application closure
That pattern has come to be called an immediately invoked function expression or iife. Not sure I like the name, but there you go. Anyway, it doesn't necessarily create any useful closures. A closure is only useful if a function creates variables that become bound to some other execution context that survives beyond the life of the function that created them (I hope that doesn't read like gobbledy-goop). You don't need an iife to create a closure.
However, you can use the above pattern to create closures since it's a function much like any other function.
Within the application closure:
> TWTR.Widget = function(opts) {
> this.init(opts); }; (function() {
> // Internal Namespace.
> var twttr = {}; })();
Some methods are marked public, others
private, and the only difference seems
to be the naming convention (private
starts with underscore '_').
The use of "public" and "private" are a bit misleading in javascript. The use of underscore to start identifer names indicates something that should only be used within the current scope, or by the "library" code itself. It's a bit redundant since the code should have a published API and any method that isn't part of the API shouldn't be avaialble externally.
But that is largely a matter of coding style and personal preference.
Is it designed using the module pattern?
Richard Cornford's "module pattern" is just that, a pattern. It's handy for simulating "private" variables in javascript, and also to share properties between functions or methods other than by the usual prototype inheritance. widget.js might be implemented (in parts) using the module pattern, but it it was likely designed by considering requirements and functionality. ;-)
Why or what benefit do you get with a closure within a closure?
Exactly the same benefits of any closure as stated above. Accessing variables essentially by placing them on an appropriate part of the scope chain is essentially the same as accessing properties via a [[prototype]] chain, only with (very different) mechanics - one uses identifier resolution on the scope chain, the other property resolution on the [[prototype]] chain.
Edit
One drawback is that the entire activation object that the closed variable belongs to is probably retained in memory, so if you just need access to a shared variable, better to consider some other scheme, perhaps even classic prototype inheritance. Or at least if you are going to use closures, try to keep the related activation object as small as reasonably possible (e.g. set any variables that aren't used to null just before exiting).
e.g.
var foo = (function() {
// Variables available for closure
var a, b, c;
// Use a, b, c for stuff
...
// Only want closure to c
a = null;
b = null;
return function() {
// use c
}
}());
Since they load the widget.js before jquery, this means widget is designed to run w/o jquery since order matters correct?
I can't access the linked resource right now (corporate blocking of twitter domain), but the load order suggests you are correct. However, some code execution might be delayed until the document is fully loaded so it isn't a guaranteee, you'll need to look at the code.

Categories