JavaScript 1.8 provides a huge amount of tasty syntactic sugar, mostly by functionalists. But very few developers know about this beauty. Of course, unfortunately, even Chrome doesn’t support all these goodies (let alone IE?), But only Firefox 3+, but the JavaScript developer just has to know about all these new products.
The most complete information can be found in the articles on
MDN :
And I translated a small, but interesting article by John Resig (author of jQuery), which reveals some of the new features in it: Expression Closures, Generator Expressions, __iterator__, Array Reduce and something else:
')
Although the article was written in 2007, I did not find its translation into Russian and there is generally enough information on this topic in Russian. All the code in the examples works fine in Firefox 3+.
Progress in JavaScript 1.8
If you have not followed the progress in the development of JavaScript 1.8, I offer you a quick overview of what is already in the nightly build of Firefox 3.
So far, the latest versions have added three main features, and more are expected. The main objective of this “light” version is to bring the current JavaScript implementation to the desired JavaScript 2 specification.
Lexical closures (Expression Closures)
Lexical closures have recently been added to the trunk, and they will certainly be interesting to functional programming lovers. In fact, it’s just an elegant entry for writing simple functions that make a language like typical lambda notation.
Let's look at the syntax of lambda functions in different languages:
Python:
lambda x: x * x
Smalltalk:
[ :x | x * x ]
JavaScript 1.8:
function(x) x * x
Javascript 1.7 and up:
function(x) { return x * x; }
Perhaps my favorite example is setting an event handler:
document.addEventListener("click", function() false, true);
Or in combination with this notation and some functions used for arrays from JavaScript 1.6:
elems.some(function(elem) elem.type == "text");
This will give you an elegant JS / DOM code.
Generation Expressions (Generator Expressions)
This is another new example. It is more complicated than the previous one, as several concepts are covered here. Specifically, the example requires knowledge of most of the features of JavaScript 1.7 - especially iterators, generators, and array generators. This feature is based on generator expressions borrowed from Python.
In the ticket tracking this feature, Brendan posted an elegant and functional solver Sudoku, written using the new syntax offered by this add-on. This demo version is based on a
similar , written in Python, which demonstrates the use of generator expressions.
For a better understanding of the meaning of this function, let's look at the sample code for JavaScript 1.8, taken from the Sudoku solver.
dict([s, [u for (u in unitlist) if (u.contains(s))]] for (s in squares))
This expression relies on the dict () function, which takes a 2xN matrix and converts it into a key / value pair. Here is its code:
function dict(A) { let d = {} for (let e in A) d[e[0]] = e[1] return d }
Let's look at each element of this expression for a better understanding of what is happening.
[u for (u in unitlist) if (u.contains(s))]
The first part of the expression is an example of generating arrays from JavaScript 1.7. Namely, we go through each item in the list.
and create an array with indices that contain s.
[s, ...] for (s in squares)
The second part of the expression is another example of array generation. At first glance, this is another feature of JavaScript 1.7 — destructive assignment, but it is not.
Destructive assignment occurs when you assign a new value to an old array element — and here we add this value to a new array. New two-dimensional arrays will subsequently be passed to the dict function.
dict([s, ...] for (s in squares))
This is where the magic is hidden. In JavaScript 1.7, we can call the dict () function like this:
dict([[s, ...] for (s in squares)])
Note the explicit use of list generation. The problem with the additional generation lies in the fact that it must be executed completely to build the whole array (which is converted into a dictionary / hash). However, the absence of one more [...] and determines the expression-generator. This makes the JavaScript 1.8 line equivalent to the following JavaScript 1.7 line:
dict((function(){ for (s in squares) yield [s, ...] ; })())
Here you see that the generator expression creates an array lazily - that is, the values ​​will not be generated until they are needed in the dict () function (as a result, we get fewer operations and better performance)
Here is another example of a generator expression:
Of course, the val_iter () function can also be built using JavaScript 1.7, using yield:
function val_iter(obj) { for (let x in obj) yield obj[x]; }
Generator expressions will be particularly useful in code that is greedy for memory and CPU - for example, in the same solver Sudoku, because now you can get the results of solutions only when they are needed - and not calculate them in advance.
Having fun with iterators
By the way, I recently already dealt with iterators and generators - and I lacked the possibility of a simple iteration over a set of numbers (for example, 0-9). Having worked with a file a bit, we can add this feature to the language:
Maybe dupe, but I was in the wildest delight of it.
Array Reduce
The last thing to understand is the new Array.reduce / Array.prototype.reduce methods with JavaScript 1.6 Array Extras.
You can apply reduce to an array like this:
someArray.reduce( fn [, initial] );
with the function, it will look like this:
someArray.reduce(function(lastValue, curValue){ return lastValue + curValue; });
The lastValue argument is the result of the callback of the reduce function. When you first call lastValue will be equal to the first element of the list or the value of initial, if you passed it, and the value curValue - the next element of the list
Thus, if you want to find a sum of numbers from 0 to 99, you can do it as follows (using JavaScript 1.8 and the above numeric iterator)
[x for ( x in 100 )].reduce(function(a,b) a+b);
Elegant, isn't it?
You can also use reduce for things like merging multiple DOM nodes into a single array:
nodes.reduce(function(a,b) a.concat(b.childNodes), []);
Try it yourself!
Everything I mentioned above works in the latest builds of Firefox 3, so if you want to try out one of the above, just do the following:
1. Download the nightly build of Firefox 3
2. Create a page that contains the following tag (with the 'version = 1.8' attribute that has just been added):
<script type="application/javascript;version=1.8"> ... your code ...</script>
And that's all you need - enjoy!