You are currently browsing the archives for the javascript tag.

Namespacing JavaScript

One of the biggest drawbacks in JS is the lack of proper namespaces. Some have long used objects to avoid global pollution, but I think it's possible to go further. That's how I came with those two functions :

(function (global) {
    bundle = function (name, func) {
      var cur = global;
      var name_arr = name.split('.');
      for (i = 0, ilen = name_arr.length; i != ilen; i++) {
        var n = name_arr[i];
        cur = cur[n] = cur[n] || {};
      }
      if (func) func.call(cur);
    };
    fetch = function(imports, func) {
      var ob = {};
      var inject_bundle = function (name, ob) {
        var name_arr = name.split('.');
        var cur = eval(name_arr[0]);
        for (i = 1, ilen = name_arr.length - 1; i != ilen; i++) {
          var n = name_arr[i];
          cur = cur[n];
        }
        var last = name_arr[name_arr.length - 1];
        if (last == '*') for(k in cur) ob[k] = cur[k];
        else ob[last] = cur[last];
      }
      if (typeof imports == 'string') inject_bundle(imports, ob);
      else for (k in imports) inject_bundle(imports[k], ob);
      return func.call(ob);
    };
  })(this)

bundle is used to create a new namespace, given as a string. If a function is passed as a second argument, then it is called, bounded to the namespace. For example, one could use the following :

bundle('net.friggeri.foo.bar', function () {
    this.bleh = "I'm a turtle !";
  });
bundle('net.friggeri.quux', function () {
    this.a = 32;
    this.b = 52;
  });
print(net.friggeri.foo.bar.bleh);
print(net.friggeri.quux.a * net.frigger.quux.b);

You might think (and you'd be right) that having long names can be a pain (I would never use something like net.friggeri.quux.a). However, using the fetch function, you can populate an object with whatever slots in a given namespace. Then, using with, you can emulate some kind of pythonish import statement. An example might be useful at this point:

fetch([
  'net.friggeri.foo.bar',
  'net.friggeri.quux.*'
],
function () { with(this) {
  print(bar.bleh);
  print(a*b);
}})

The code is pretty ugly: I have to use eval at some point to make sure it still works if called in a nested function and I didn't find a way to avoid using with in the function passed to fetch. Of course it's possible to use a this.bar.bleh syntax, but the whole point of fetching the contents of the bundle is to avoid using such long variable names.

If you wish to expand this, or have any suggestions, you're welcome to comment.

Update : I just realized that it could be simplified a lot with having fetch returning directly the object, allowing something like :

with(fetch([
  'net.friggeri.foo.bar',
  'net.friggeri.quux.*'
]) {
  print(bar.bleh);
  print(a*b);
}

This is a very good example where having an all functional approach might not be the path to follow. ;)

JavaScript Shell Scripting

A few days ago, Peter Michaux posted a very promising article concerning xjs. I've long wanted to be able to use JS to write shell scripts (as one would do using bash, python or perl) but it lacked several important features.

Peter has added a File module which wraps Java file operations, and I see this as the first step towards taking JS out of web development. Let's face it, JS is really present in browsers, SSJS is taking off very slowly and even though a few apps use JS for scripting, it's still not mainstream.

The way I dream of JavaScript's future ? As a general purpose scripting language. This means that several things have to be done. First, an easy way of binding whatever library to JS. Second, a CPAN like repository dedicated to JS. There is absolutely no control on how would evolve the latter. The former, however, can be conceived right now.

I'm not really sure if I agree with Peter's choice of Rhino instead of SpiderMonkey, but I guess he has more experience with Java than with C — which is quite the opposite of my own misconceptions. I guess there are pros and cons for each of the choices, but I wonder if it'll be easy to port generic C libraries to JS using Rhino. I must clarify something at this point : I have a deep hatred of Java — it's a kind of zealous religion — and everything that comes near it appears like obscure magic to me.

Nevertheless, I really wish a lot of good things to xjs, and I hope that Peter will take into account the fact that an easy mechanism for porting library is a must-have.

VI in JavaScript

Completely useless but nevertheless awesome : jsvi is an implementation of Vi in Javascript which support several useful features, among those visual lines are really appreciated. I'm not quite sure how this may be used in everyday life, but I'm sure it could be adapted to replace textareas (without filling the whole page), allowing us to use more efficient text inputs than all the cluttered What You Get Is All But What You Want stuff we find nowadays.

One huge drawback : the :emacs command, why is this even implemented ?

A cool addition would be an implementation of auto completion, like the one I developed in Jim.

Emulating catchall, getter and setter in JS

Getters and Setters are cool stuff, so is the notion of catchall. And, if it's a nice feature, it has to be implemented or emulated. I don't have nothing much to say about this except that I did it and that it works. The syntax isn't really nice, but it's usable. I used the same examples used here.

function CGSobject (catchall) {
  var o = function (k,v) {
    if (v) {
      var curv = o.content[k];
      (curv && curv.set && curv.set.call(o.content,v)) || (o.content[k] = v);
    } else {
      var v = o.content[k] || o.catchall(k);
      return (v.get && v.get.call(o.content)) || v;
    }
  }
  o.content = {};
  o.catchall = catchall || function () { return null };
  return o;
}

var o = CGSobject(function (x) { return x+1; });

// basic set
o("a", 7);

// basic get
print(o("a"));
// -> 7

// getter
o("b", {get: function () { return this.a+1;}});
print(o("b"));
// -> 8

// setter
o("c", {set: function (x) { this.a = x / 2 }});
o("c", 50);
print(o("a"));
// -> 25

// catchall
print(o(2));
// -> 3
print(o("foo "));
// -> "foo 1"

What Server Side JavaScript needs

A few of use are convinced that SSJS is the way of the future, in terms of elegance and simplicity (using just one language for both client and server), etc. However, if we wish that one day JS beat PHP1, there are several conditions.

First of all, I think the main drawback is inertia. PHP is currently the way to go in web development (even though a few still use ASP, CGI, etc.). In order to counter the inertia, any new server side language has to be as good as PHP (not so difficult to do), as easy to learn and have exciting new features.

Python and Perl have been around for quite some time, without becoming dominant, so I guess that they won't in the future.

Some said that RoR was that alternative, and let's face it : it's trendy among Mac geeks using textmate… Not that I have anything against this, but those developers live in another world: RoR has basically several flaws which can't be overcome. First, it doesn't scale2. Second, it doesn't have a C-like syntax3, and this has a psychological impact on devs coming from the PHP world. Third, it's yet another language to learn. Fourth, it didn't play well under Apache until recently. The reason why some guys switched to RoR could be summed up to three points: the MVC model, the Active Record pattern and scaffolding.

All those ideas are nice, but it's not enough for RoR to be the Next Big Language. SSJS is exploding right now, with quite a number of solutions being developed. However, most of those are bloated and are either ports of PHP or RoR to JS. The only one which takes it to another level is Jaxer, which is a nice concept, but is intrinsically unscalable: how can one imagine having hundred thousands instances of DOM trees being manipulated at the same time on the server and being delivered quickly ?

I believe that the JS strength resides not only in the fact that it's usable on the client, but also because it's prototype based. For example, Active Record is something nice for class based object orientation, but I believe that there are much simpler approaches using prototypes.

Nevertheless, unless someone comes up with some revolutionnary features for SSJS, I'm afraid that it'll stay a niche language (on the server).

  1. This is not a joke []
  2. For example, Twitter is abandonning RoR, for that reason []
  3. no curly braces, no semi-colons []