JavaScript in 2015

Last modified by Guillaume Delhumeau on 2023/03/09 11:37

Jul 20 2015

Since its beginning in 1996, JavaScript and its usage has changed a lot. In this article, I am going to describe a brief history of it and how it is used today in our browsers.

Brief History

  • JavaScript is an awful language created to add dynamical content to web pages (1996).

 Why is it awful? 

  • A language with prototype instead of classes. Seriously?
  • '===' vs '=='
  • 'this' does not work like any other language
  • each browser have specific extensions and/or DOM elements
  • a lot of unexpected behaviours
  • and many more
  • and many more...
  • and many more...

At first, it was mainly used for form validation: ie ensure a form has been properly filled before actually sending it.

Then, Microsoft invented the XMLHttpRequest object. Thanks to it, it was possible to perform some requests in JavaScript. So it became possible to request the server in background and refresh some parts of the web page according to this, without refreshing the whole page.

This technique has then been called AJAX, for Asynchronous JAvaScript and XML.

  • Asynchronous: the code execution is not stopped until the HTTP request is terminated. It actually runs in background and a callback is executed at the end.
  • JavaScript: the language used to dynamically update the page.
  • XML: the data returned by the server and that javascript parse to update the page. Nowadays, it is often replaced by JSON.

Then some impressive websites/applications emerged. On my own, I was really impressed when Gmail came out.

Some attempts have been made to create better languages than JavaScript in the browser:

  • Coffee Script (can compiled to JavaScript)
  • GWT (Transfrom Java code to JavaScript - The XWiki WYSIWIG editor uses it)
  • Dart (by Google)
  • the new one: TypeScript (by MicroSoft)

Until now, no one has been successfully integrated in all major browsers. And when they are translated to JavaScript, it is just a nightmare to debug.

Conclusion: even if it's awful, JavaScript is indispensable to create modern web pages.

Libraries

To deal with the language and browser's limitations, some people developed libraries that make javascript development easy.

The most famous one is jQuery, and it reached a point that it is now considered as a standard library that almost everybody use.

An other popular library: Prototype (used by XWiki but not active today).

We have also amd.js (implemented by require.js) that introduces the ability to split the code into different modules that depends from each others.

Current frameworks

The traditional way to develop a web app was to create some HTML pages served by the server and then add dynamic behaviours on it with JavaScript.

<body>
<h1>Welcome to my application</h1>
<p>There is currently <span id="tweetCount">42</span> tweets about JavaScript.</p>
</body>
<script language="javascript">
// Refresh the tweet count every 10 seconds
setInterval(function() {
 // Perform an AJAX request to the server to get the current count
 $.ajax('/rest/tweet/java/count', function(data) {
   // Update the UI
   $('#tweetCount').update(data.count);
  });
}, 10);
</script>

Some people though that it would be more efficient to let JavaScript manages the whole UI and to only use the server to get some data as JSON documents.

They had introduced some concepts.

Two-ways data-binding

Problems:

  • it's a pain to update all dynamic data displayed in the page.
  • more generally, it's a pain to maintain a synchronization between data displayed on the page and the variables we have in the JavaScript program.

Solution:

  • create a model of 'observable' variables.
  • Any change done on the model will affect the UI.
  • Inversely, any change done on the UI will affect the model.

Example with KnockoutJs:

First we define a model containing these variables:

function MyModel() {
 this.userName = ko.observable();
}
ko.applyBindings(new MyModel());

Then we use it in the page:

<form>
  <label for="userNameField">User name:</label>
  <input type="text" data-bind="value: userName" />
</form>
<p>Hello <span data-bind="text: userName"></span>!</p>

See the live example

Same example with AngularJs:

myApp.controller('mainController', function ($scope) {
  $scope.userName = '';
}
<html ng-app>
<body>
<form>
  <legend for="userNameField">User name:</legend>
  <input type="text" ng-model="userName" />
</form>
<p>Hello {{ username }}!</p>
</body>

See the live example

You can also send the new value to the server:

MyModel.firstName.subscribe( function(newValue) {
 // Send an AJAX request to save 'newValue'.
});

Cascade

You can define 'observable' variables depending on other variables:

 Here with KnockoutJs:

function MyModel() {
 var self = this;
       
  self.firstName = ko.observable('Bob');
  self.lastName  = ko.observable('Smith');

  self.fullName  = ko.computed(function() {
     return self.firstName() + ' ' + self.lastName().toUpperCase();
  });
}

See the live example

And when a change is performed on firstName, it also update fullName and everywhere it is used in the UI.

Now imagine how you can easily create complex UI with this system!

Templating

Problems: 

  • it's a pain to create new DOM elements in the page with JavaScript.

Solution: 

  • create a template system (such as Velocity, JSP, etc...) directly in JavaScript

Example with KnockoutJS:

<table>
  <tr>
    <th>Name</th>
    <th>Balance</th>
  </tr>
 
 <!-- ko foreach: accounts -->
    <tr>
      <td data-bind="text: name"></td>
      <td data-bind="text: balance"></td>
    </tr>
 <!-- /ko -->
</table>

<div data-bind="if: userName">
  <p>Hello <span data-bind="text: userName"></span>!</p>
</div>

See the live example

Example with AngularJs (not tried):

<table>
  <tr>
    <th>Name</th>
    <th>Balance</th>
  </tr>  
  <tr ng-repeat="account in accounts">
    <td>{{ account.name }}</td>
    <td>{{ account.amount }} €</td>
  </tr>
</table>

<div ng-if="user == 'Admin'">
  Hello Admin, ...
</div>

Example with Handlebars (used by EmberJs) (not tried):

<table>
  <tr>
    <th>Name</th>
    <th>Balance</th>
  </tr>
  {{#each accounts as |account|}}
    <tr ng-repeat="account in accounts">
      <td>{{ account.name }}</td>
      <td>{{ account.amount }} €</td>
    </tr>
  {{/each}}
</table>

{{#if user == 'Admin'}}
<div>
  Hello Admin, ...
</div>
{{/if}}

Routing

Problem:

  • how to have an URL that reflects the current state of the application so I can share it?

Example:
I'm looking at the issue number #42, then the URL is: myApp/issue/42.

Solution:

  • using a router.

Example with AngularJs:

myApp.config($routeProvider) {
  $routeProvider
    .when('/issues', {
      controller: 'mainController',
      templateUrl: 'templates/list_of_issues.html'
    })
    .when('/issue/:issueId', {
      controller: 'issueController',
      templateUrl: 'templates/issue.html'
    })
    .otherwise({
      redirectTo: '/issues'
    });
});

Example with Sammy:

Sammy(function() {
 // Handle "/issues" URL
 this.get('issues', function() {
   // Do whatever you want
   model.currentView = 'issues';
  });

 // Handle "/issue/xxx" URL
 this.get('issue/:issueId', function() {
   // Do whatever you want
   model.currentView = 'issue';
    model.currentIssue = this.params['issueId'];
  });

 // Handle the default URL
 this.get('', function() {
   // Redirect to "/issues" with the "get" method
   this.app.runRoute('get', 'issues');
  });
}).run();

See the live example

Drawbacks

  • The applications using these frameworks are more difficult to debug ("why this template is not working?", etc...). Some of them provide browser extensions for this purpose.
  • SEO: the robots do not index these JavaScript's URLs. A typical solution is to provide a static version of these pages, but it's more work...

Conclusions

0day.jpg

A quick list of competitors: AngularJs, KnockoutJs, EmberJs, ReactJs (by Facebook), Backbone.js, Polymer.js, Meteor, Aurelia, Durandal, ...

Each framework propose its own implementation of the same main ideas. Some of them are quite easy to understand (KnockoutJs), and some others have an harder learning curve (I think about AngularJS with its concept of controller, dependency injection, directives, etc...). Most of them are sponsored by enterprises.

So which one to use?

The JavaScript world is evolving very very quickly. The community's favourite framework can be out of fashion 6 months later... 

It's a bit early to know which will win the fight and it proves that the JavaScript world is not sufficiently mature. Create a modern JS applications and being on the top is a challenge and it is actually risky.

The AngularJs case

AngularJs may be the favorite framework right now. It seems to have a great community and the fact that it has been a Google project has made a lot for its credibility. People said "if it's Google behind it, it must be serious!".

Because of that, we have developed, at XWiki, an AngularJs application called "File Manager Application". It's a great application that prove the power of both AngularJs and XWiki.

But recently (october 2014), the AngularJs developers announced that they were developing Angular 2 and that it will not be retro-compatible with existing apps!

The migration path is not fully ready yet and Angular 2 does not support old browsers such as IE9...

Conclusion: it's very risky to start a new application with AngularJS right now since Angular 1.x will be dead soon or later and we don't have any perspective about Angular 2 yet. Will it be good enough? Will it be popular and maintained on the long run? Nobody could say...

Stop using framework?

This announcement came as a blow for a lot of developers who believed in AngularJs.

A popular idea right now is to stop using big frameworks that try to do everything and replace them by a collection of little libraries: one for the data-binding, one for the templating, one for the routing, etc... So if one library is abandoned, then you only change the code that was using this library, not the rest.

Personal thoughts

  • AngularJS: seems a bit complicated to understand with unique concepts (directives, factories, services) that you don't have in other frameworks
  • KnockoutJs with Sammy: I've made some experiments and it was a quite nice and easy to understand. It plays well with other libraries (require.js, jQuery) and it's only a small file (54Kb minified) to include in your project. People helped me on IRC when I have troubles.
  • EmberJs: looks promising but I give up when I have discover that it is designed to be used with an EmberJS backend in addition with your own server.
  • For a content-oriented website, I don't think there is a lot of benefits to use these new technologies, because it's not necessary and because it is harder to index in search engines. But for a complex application (that may not need to be indexed anyway!), it is very powerfull.

ES5/6/7

JavaScript has been normalized by the ECMA organization and we should actually call this language ECMAScript (which nobody does).

Annotations? Promises?

TypeScript

Developed by Microsoft, this new language is used by Angular 2. Let's see how it evolves.

 ...