2

In the discussion here, the comments in the accepted answer suggest that I approach the given code from a functional perspective, which was new to me at the time. Wikipedia said, among other things, that FP "avoids state and mutable data", which includes according to the discussion global vars. Now, being that I am already pretty far along in my project I am not going to learn FP before I finish, but:

  1. How is it possible to avoid global vars if, for instance, I have a UI whose entire functionality changes if a mousebutton is down? I have a number of things like this.

  2. Why was there a strong negative reaction among some experienced coders to implementing FP in JS? When I brought up what seemed to me to be supportive comments by Crockford, people got even madder. Are there strong arguments against using fp in JS? What constitutes a "functional language" and why is JS "not it"?

12
  • Javascript is not really a functional language, so trying to emulate it in javascript would be very cumbersome. Better to choose a FP language to code in directly (can't give a reference to any good web script FP language)... Commented Jul 7, 2012 at 21:19
  • +1 I also experience the same reaction. It is a good question, in that, this intangible but otherwise common curious reaction is worth review, for reasonng - and perhaps improvement in years to come. I will consider and answer shortly.
    – Jack Stone
    Commented Jul 7, 2012 at 22:04
  • 3
    Please split this into two separate questions as they are so different.
    – ChrisF
    Commented Jul 7, 2012 at 22:13
  • @Paxinum Javascript is not a functional language but some of the patterns used in functional languages (especially those that take advantage of first class functions) also happen to be very beneficial in js. Commented Jul 7, 2012 at 22:36
  • 1
    Well now that he dropped it, there's no context. "some experienced coders" means nothing. "I posed the issue on some IRC channel and encountered an avalanche of hate" puts it in perspective. Again, what is the point of all this meta-question-criticism on Stack? It's not useful or helpful to get that hung up on the details. There's a valid topic here. He didn't name the IRC channel or say non-FP was stupid. It's partially about implementation and partially about culture. Commented Jul 8, 2012 at 1:42

2 Answers 2

5

Please note: There is never an excuse for being a total douchebag. I am not justifying bad behavior on IRC but hopefully this will offer some perspective.

  1. Avoiding global vars is easy. If I understand FP correctly however, the idea is to avoid generalized state altogether. This does not jive well with closure/event-driven UI work, IMO, which are two things JavaScript is very good at. You should of course, be careful to avoid letting state become overly generalized to the point where a wide variety of objects can be responsible for changing it. When tempted to make state completely global, you should be asking yourself if you shouldn't be creating a composite object of several smaller UI objects that owns responsibility for that state.

  2. Crockford's done a lot of good work but we don't all revere him as some sort of god and I for one disagree with a lot of stuff he's declared "the bad parts" of JavaScript. I also find most of JSLint's default rules excessive, silly, and overly reflective of one developer's personal coding preferences. Function hoisting for instance, is fantastic. I love getting straight to the business logic in my apps at the top of my objects and callback functions and declaring the inlines below. FP itself seems overly procedural, IMO. Complex UI, which you don't see a lot of on Yahoo, is better served by a more loosely-coupled, event/messaging-driven paradigm in my experience. JS derives it's flexibility and power from closures and first-class functions. Not having any upper layers where state can be referenced isn't really a great fit with that, IMO.

Edit: Avoiding global vars

(function(){

    var comboBoxesLoaded = false;

    comboBoxesLoaded = UI.ComboBoxFactory.initiateComboBoxes();
    //builds comboboxes and returns true

})()

alert(comboBoxesLoaded); //undefined error here.

Technically, you're not declaring a global var. comboBoxesLoaded is a state var scoped in an anonymous function but it's better to have a comboBox object that maintains its own state and also manages stuff like one (or several) comboBoxes loading in new data when another is changed.

All this does is avoid global namespace collisions, which is good, but you're still maintaining state in an overly general space where anything else you drop inside the anon function could hit it. (the idea behind this pattern is that you drop a ton of your code inside that anon function so you don't have to sweat blowing up other code you don't control by accidentally giving a global var the same name)

But it's stil better to let your combobox factory manage that state. It can listen to other objects to make changes but when you're certain you know only the factory is actually putting its hands on its own internal state vars you have one central point to go to when you're wondering why you're encountering an unexpected state at some point of breakage and the object itself can keep track of who it was listening to last.

Example of composite objects? That's getting into writing a small app territory. Maybe later.

4
  • It's not that I'm offended, it's more surprised =P. Could you show examples of avoiding states and/or composite objects you mentioned in (1)?
    – jamesson
    Commented Jul 7, 2012 at 21:33
  • Event driven programming is not the only way to write UIs. I suggest you take a look at some reactive programming libraries for Javascript: they can actually make your event-driven code simpler, elegant and more functional. Commented Jul 7, 2012 at 23:58
  • 1
    Name 'em. I'll have a look. I'm open to new ideas. Commented Jul 8, 2012 at 1:36
  • @ErikReppen: Check out FlapJax. If you don't mind a slightly more abstract library, check out Arrowlets which adds Haskell-style arrows to JavaScript. If you're into C#, there is RX.js which is a port of C#'s Reactive Extensions (RX). I've only played around with the latter two, and liked Arrowlets the most, but I'm rather partial to Haskell and so naturally biased :P. Commented Jul 9, 2012 at 9:18
3

In the post that you reference, first off, I agree fully with the advice of @lwburk He writes a very nice answer.

Secondly, I'd like to quickly address the "functional programming" aspect, this may be distracting, potentially not what was originally intended, and is a good candidate for inviting comments that diverge from the core issue here.

So, I would like to expand on the advice of @lwburk, and on your follow-up question, as it is a valid Advanced JavaScript question:

How is it possible to avoid global vars?

At a high-level, what is being referenced here is a Design Pattern in JavaScript called (among other names) the Namespace pattern. It is fundamentally beneficial, but... as with any design pattern, it is possible to over-use, while uncommon, into an anti-pattern. Which sounds to me, like your counter-argument. So, let me explain... please hear me out.

The reasoning behind limiting global variables boils down to a simple purpose. We wish to avoid naming conflicts, collisions, or otherwise clobbering of variables as others come into scope... with the same name - at runtime. There are other reasons, but this is the primary one.

To me, this may be potentially simple, because if your environment has minimal change, and the chance of clobbering is minimal, then this pattern is, in some cases, not implemented for its intended purpose,

but... following this pattern uniformly has an upside of object-oriented encapsulation, and this reasoning is why it is commonly recommended for all environments.

Encapsulating data within an object makes it modular, in addition to protecting it from clobbering. Here is the pattern:

var app = app || {};

app.init = (function() {

  // Private vars and methods 
  var foo; // ...

  // Methods in here are public
  return {
    method: function() {

    }
  };

}());

Now, just look at the app variable for the namespace, the internal part is an advanced topic called Closures and IIFE(Immediately invoked function execution) at first it looks egyptian, but get used to it, soon it becomes an old friend. It looks like this:

(function() { var x; //here function xy (){} //here

// do Stuff here.

}());

This is a really important pattern!

The reason is that it allows you to turn JS into an oozy play-doh like substance. What the heck do I mean? Encapsulate all your variables within a named object. Now they can maintain state and float around in your single global member "namespace". Why is this a flexible substance? I'll get to that in the answer to the second question, as they seem related. But for now realize that this pattern allows JS to become highly transient: once modular.

Be warned, this is the beginning of Advanced JavaScript - not the end. Allowing one object to communicate with another namespaced objects is, yet another, advanced topic.

Quick Tangent:

*To keep objects nicely modular and decoupled, send events between an intermediary not direct references (it is so easy to do so) between all objects. References become a maintenance-nightmare. Look up PubSub or Evented Views for this tangent.

Let me explain why flexibility may cause mixed-reaction.

Why was there a strong negative reaction?

Such a good question, worthy of a psychological or socialogical review. And we dont have time. More often than not, when speaking about Advanced JavaScript - for whatever reason... a strong negative reaction can occur. Have you observed this in practice, yes?

  1. it may be that the original question is inflammatory,

however, I see here you are asking an honest question of serious intent. So let me please dismiss that speculation.

  1. The other possibility is that, potentially, there is a negative reaction external to your question. Wait that is strange? What? Why?

There seems, an unspoken stigma. A misconception. Anyone know what I am talking about - have you observed this? Something, somehow, somewhere - there is a n embedded reaction... JS has a tangled history with naming, confused with Java,... misunderstood as a 'Toy-Language' and yadda yadda yadda,

(look up Enter the Dragon - Dmitry Baronovski) That said, there is another > point I wish to raise here that is far more important and that is.... flexibility.

Flexibility

JavaScript flexibility causes... different perspectives.

JavaScript is very flexible language. No? It is so flexible, to the point, that it can be squeezed out one hole and become a server(node.js), another and become a datbase (MongoDB), another and become MVC (backbone) and yet another and become a rich enterprise framework (ExtJS or jQuery)... and don't forget Mobile; phonegap, or Build: grunt. This is remarkable. It is like play-doh. Yes a toy-language indeed.

So now lets consider how JS exists in CoffeeScript, or GWT, Dart, or Windows 8. They are remarkably different beasts.

This comes full circle to the controversial point raised earlier that "functional programming" conversation might be "distracting". In all respect, let me clarify, "functional programming", while it can be defined at wikipedia - has a very good chance of a spudo-philosophical meaning that ends up meaning something slightly different to all of us.

The fact is, JavaScript can be seen in so many different ways (paradigms), that we should, at some point, think about viewing it through different lenses. JS exists in many context domains, it is a point of significant growth, and will be even moreso in the future.

The problem here, with this, is us. Honesty is the best policy and here is my humble pie. The problem is that it is an 'invisible fruit'. Please bear with me, I have a point...

Invisible-Fruit

The notion is this: we all like our programmatic fruit. But code is, essentially invisible - because it cannot be consumed, digested, conceptualized... in a single glance or sitting. It must be consumed. So we tend to go... with what we know. This is primarily because, often times we bite into a pit, sometimes an orange-peel, and in the most unfortunate of occasions - a lump of coal.

It is for this reason that if some stranger hands you their invisible fruit, saying, check this out it is great... no matter what they may say - you are suspicious. Aren't you?

There are two options: 1 of agnosticism, 2 of aversion.

In order to intellectually consume the new programmatic paradigm, one must make a blind leap-of-faith and - "take a bite". Do you observe this is in practice?

So why the aversion?

Because sometimes we are biting into a lump of coal.

But more often than not, because we are biting-into a lump of code that is beneficial to another engineer in another context - but is just not beneficial to us.

Do you know what I mean?

Did you ever fervently consider the notion, which is better: jQuery, ExtJS, YUI, Dojo, MooTools, Backbone, Underscore, Require, etc...

****The take-away is this.****

JavaScript is so malleable (through the advanced code that begins with the namespace pattern) it can transcend technologies in a way that makes JS not really better or worse implementations, but just different tools for a different jobs. And some are a better fit than others. I still hear many conversations accidentally fall into this.

Perhaps, we can -eventually- begin to think about lowering our defenses. in this language of the web - this multi-paradigm, meta-morphing language, our old pal JavaScript - and see it through separate lenses.

Time and again we find, the solution depends on the context. But time and again we defend persistently- our minority experience.

JavaScript is larger than any one of us.

This is a good thing. "Enter the Dragon"

My apologies for length of perspective. I hope this helps. All the best, Nash

...

2
  • 1
    I was referring to people being nasty on IRC, not the OP for suggesting FP in JavaScript. Commented Jul 7, 2012 at 23:08
  • +1 I agree. It happens. I will edit. Thank you sir for improvement.
    – Jack Stone
    Commented Jul 8, 2012 at 6:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.