Blog-Archiv

Sonntag, 26. November 2017

ES6 Symbols

ES6: ?

Before ES6, JavaScript had following data-types:

  1. Undefined
  2. Null
  3. Boolean
  4. Number
  5. String
  6. Object

Now, with ES6, we have a new data-type:

A Symbol is neither String nor Object nor Number. The Symbol() function can be regarded as an id-generator. A symbol instance is an unique identity.

Purpose

Symbols should be used as an alternative to property names. Properties are always public, and thus vulnerable. If you store something into a DOM-node as a named property, some other library may have chosen the same property name, and may overwrite your value. This is not possible if you use a symbol as key, instead of a string, because symbols are unique and runtime-generated.

const displayed = Symbol()
// ....

domNode[displayed] = true
// ....

if (domNode[displayed])
    decorate(domNode)

Such symbol-properties are not private, but at least they are a way to separate concerns, and get away from all those dubious string property bindings.

The only atrocity is that you always need to use the square-bracket notation myObject[mySymbol]. The conventional dot notation myObject.mySymbol does not work!

Also be aware that symbol-properties don't get serialized (→ transient), so they won't arrive on the server when their wrapping object was sent by AJAX.

ES6 Symbol Tests

Work through examples below to get familiar with symbols. Click onto one of the buttons to get example source code into the text field. In the area below it you can find explanations about the example.

  •  
  •  
  •  
  •  
  •  
  •  
Description

Resume

String bindings make all programming languages vulnerable, even compiled ones. Unexperienced programmers often stick to such notations, because they think it makes the code understandable. Yes, may be true, but it is also dangerous. You can not control thousands of lines of code just by understanding them. You need encapsulation mechanisms. ES6 symbols are a very welcome alternative to string-properties.




A Symbol() call is like retrieving a value from a database-sequence. You always get a new value that was not yet used. You could also call that "id-generator".

The optional parameter to Symbol() is just for debugging purposes. It does not influence the generated symbol in any way.

It is possible to put values into objects using symbols as key in square brackets. Take care to remember the symbol somewhere, else you will not be able to retrieve the value any more.

It is not possible to access symbol-properties using the dot-notation. This does not throw an exception, but you will get back undefined.

You can not construct symbols using new Symbol(). This throws an exception.

Symbols can not be stringified. When used in string-concatenation, an exception will be thrown. This will be quite demanding for console.log() debug outputs ....

Symbols in objects can be found out by by Object.getOwnPropertySymbols(). You get back an array of all symbols that have been defined on the given object. But the Object.getOwnPropertyNames() function and the for-in loop do not find symbols.

Symbols do not get not serialized like properties.

You can create global symbols using Symbol.for() and Symbol.keyFor() functions. That way you can bind a symbol to a string identifier. After creation, the symbol is immutable, like a constant. This can also be useful as enumerations.

This is the way how you can convert a symbol to a string.
See also "Nature of Symbols, Part 2" about the problems with converting symbols to string.

Dienstag, 21. November 2017

ES6 Object Property and Function Definitions

ES6 brings a new syntax for object definitions that may baffle JavaScript programmers a little. I am not sure if we really need these features, but they are there and will be used, so we have to learn them. Most irritating may be the "computed property names".

ES6: ?

ES6 New Object Syntax Tests


  •  
  •  
  •  
  •  
Description

Postface

Having real maps, supported by the language itself, is a great relief. Nevertheless still immutability is missing. We would need it for both object-functions (would make them real methods) and properties (constants within objects).

The object testObject is constructed in a different way than it was done in JavaScript. Its two functions foo and bar are put onto the object without the use of colons, not even the keyword function is used. This gives ES6 a concise and elegant object construction.

Mind that still we do not have immutable object functions!

The object testObject is constructed without the use of colons. Just make sure that variables of same name as the object properties exist before, and you can copy them into the object. Changing a variable value afterwards does not affect the according object property.

Mind that still we do not have immutable object properties!

In JavaScript it was not possible to have an expression on the left side of a property definition. In ES6 it is. We need to get used to that: the square brackets here are not related to an array!

Here, an object is built by first defining a property foo, in a traditional way using colon. Then, on the left side, there is a square-bracket expression containing a function call. Whatever the outcome of that expression is will be taken to be the property identifier. The function computePropertyName simply returns the given parameter.

Mind that we still have just strings on the key-side of an ES6 object, no numbers or objects!

In JavaScript, objects were maps and maps were objects. Just that the map-key was always stringified, because it had to be a property name. In ES6 we have maps that can have a non-string as key.

As key for PI we define an object called piKey. Then we construct a map and set the key-value pair into it. Reading the first key from the map shows that it is piKey, not its stringification.

Mind that you can not put key-value pairs into a Map with the square-bracket notation: map[piKey] = 3.14159, this does NOT work!




Sonntag, 19. November 2017

ES6 Spread Operator and Rest Parameter

The ES6 spread-operator is more than C's varargs (→ variadic arguments) or Java's ellipsis. Besides expressing uncertain parameters it also can be used to create or destructure arrays.

Here is an example of a C function prototype with varargs, like written in a header.h file:

int printf(char* format, ...);

The same in Java, like written in an interface:

int printf(String format, Object ... arguments);

It got from being a "..." in C to being a typed and named "...".

In ES6 it's going to be untyped, but named.

function printf(format, ... parameterArray) {
    // Spaces can be between spread-operator and parameter-name,
    // but it's better understandable without!
}

This is called Rest Parameter. It must be the last parameter, nothing behind it.

The "..." part is called Spread Operator, and it uses iteration to destructure whatever is right of it. Thus the right-of-it must implement iterable. An Array, a Map, a String, they all do it. An Object does not.

const characters = [ ..."abc" ]

This creates an array-clone from the character-array of a string (see example below).

ES6: ?

ES6 Spread Operator Tests


  •  
  •  
  •  
  •  
Description

Resume

With ES6, you can destructure an array const oneTwoArray = [ "One", "Two" ] to function-parameters

  • either using square brackets in the parameter declaration of the function, like in function foobar([ one, two ]), calling it by foobar(oneTwoArray),

  • or using a parameter declaration like function foobar(one, two) and calling it with the spread-operator, like in foobar(...oneTwoArray).

Expressing the same thing in different ways? Hm ...

All elements of array firstArray are inserted at second position into the array firstArray. Mind that the value 100 gets shifted two positions backwards by that operation!

We have an array called parameters that we want to pass as an argument list to a function, so that the first array element is the first paramter, the second element the second parameter, and so on. Thus we put the parameters array into the call of the function, and prepend the spread-operator to destructure it.

This is called rest parameter.

The function receiveParametersAsArray receives every argument after the first one as an array named parameterArray. This resembles the classical varargs. Mind that this technique makes it absolutely necessary to document the function parameters, else no one will be abe to use this function without reading its source code, and the source code of all functions that it calls. Try to avoid the rest-parameter!

The spread-operator uses the iterable protocols, and thus can spread all objects that implement these conventions, in this case it spreads the characters of a String-object.




Mittwoch, 15. November 2017

ES6 Destructuring Arrays and Objects

In top right corner you see whether your browser already supports ES6 or not. Should you see a green stripe there, the scripts in this Blog may work, should it be red, they won't. Click on the stripe to make it disappear.

Destructuring sounds destructive, but it is not related to OO destructors in any way. Rather it is about copying array elements or object fields to variables or constants. ES6 has a special syntax for this, and it takes some time to get used to it. It is not similar to anything that existed in traditional programming languages.

Below, you find a list of buttons that each execute an ES6 destructuring example. Clicking on the button copies the script to the text area, where you can modify it, and execute it again. The description finally describes what is done in the script.

ES6: ?

ES6 Destructuring Tests

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
Mind that the script here is executed by your browser, not by some ES6-webservice on the Internet!
Description

Postface

This is how execution of dynamically fetched script code is done in ES6 (like from textarea above):

try {
    let script = "alert('Hello World');";
    const anonymousFunction = new Function(script);
    anonymousFunction();
}
catch (error) {
    alert(error);
}

First this script builds an array of numbers as constant. Then it assigns the contained array-elements to named variables by "destructuring". The let statement defines the variable names inside the square brackets (square brackets are used for array-destructuring). Leaving out an array-position is done by leaving out the name before the comma, so there are two consecutive commas. This is NOT a mistake, this is called "hole". No error happens in case there are more variable names than array elements.

The let statement can also define default values for the variables inside the square brackets. In this case, the variable c can not be assigned from a list element, and thus gets the value 99.

A special case of "destructuring" is "restructuring", for example swapping variable values.

The let statement creates variables a, b, c, and assigns values from an array to them. Then a right-side variable-grouping is assigned to a different grouping on the left side. Thus the variable values are swapped. You could have any kind of grouping on each side, just make sure that the used variable names exist before "restructuring" them.

Mind that ES6 currently fails when you have a statement without trailing semicolon, and the next line starts with a square bracket.

First this script builds an object with two fields. Then it assign these fields to named constants by "destructuring". The const statement defines the names of the constants inside curly braces (curly braces which are used for object-destructuring). These names must exactly match the names of the fields in the object. At end we have two constants with name lastName and firstName, their values where retrieved from the assigned object.

This script builds an object with just one field lastName. The let statement destructures that object, whereby firstName gets a default value in case there is no field of that name in the assigned object.

This is how you can access also fields in objects nested in parent-objects, and how you can declare default values for them. The let statement uses curly braces for each object nesting level. Mind that here the name of the local variable is on the right side of the colon, on the left side is the name of the object field.

The optional default value follows after the "=" operator. "Route 66" is not assigned, because there is such a value in the assigned object, but "Outhouse" replaces the missing object-field house.

The function foobar "destructures" its parameters first and second from a given array, thus it uses square brackets. So when we pass an array with elements "one" and "two" to it, its first parameter will have the value "one", and its second parameter the value "two".

The function foobar "destructures" its parameters firstName and lastName from a given object, thus it uses curly braces. So when we pass an object with fields firstName and lastName to it, these parameter will hold the values of the object fields with same name.




Montag, 13. November 2017

ES6 Block Scoped Constants and Variables

You may have asked yourself: "How can I recognize ES6 code quickly"? The most frequent difference to JS possibly is the occurrence of const constants and let variables. JS had var variables, and no constants. So if you see something like this ...

const yesWeCan = true;
// yesWeCan = false; /* causes error! */

... you know that it is an EcmaScript constant definition, the name of the constant being yesWeCan. A constant can be assigned a value just once, directly where it is defined. You can not change its value afterwards, like you can do it on variables.

let noICant = true;
noICant = false;

This was an EcmaScript variable definition, the name of the variable being noICant. Assigning another value causes no error.

{ Block Scope }

For Variables and Constants

The difference to JS var variables is that the ES6 let variables, and also const constants, are block-scoped.

{
    const iDontWant = false;
    let maybeICan = true;

    {
        alert(iDontWant);
        alert(maybeICan);
    }
}

alert(iDontWant); /* error, constant not known in this scope! */
alert(maybeICan); /* error, variable not known in this scope! */

This code opens a block (looks like an object declaration, but isn't). Inside the block, a variable and a constant are defined. Then another block opens, and they are used inside. So they are visible indefinitely inside nested blocks. Then both blocks are closed, and neither variable nor constant are visible any more. Both alerts would cause a runtime error.

So the ES6 block is actually the replacement for JS IIFE ("Immediately Invoked Function Expression"):

(function () {
    var jsVariableNotVisibleOutside = true;
})();

Mind that following JS code still would work, because JS variables are "hoisted" to the next enclosing function declaration, or to global scope when none exists:

{
    var jsVariableVisibleOutside = true;
}
alert(jsVariableVisibleOutside); /* not an error! */

What to learn here?

Don't use var any more when you write ES6 code, use const and let.
Prefer const, this will make your code really resistant (remember that functional languages do not allow variables!).

For Functions

Also functions are block-scoped in ES6.

{
    function foobar () {
        return 1;
    }

    if (foobar() !== 1)
        throw "Outer foobar failed!";

    {
        function foobar() {
            return 2
        }

        if (foobar() !== 2)
            throw "Inner foobar failed!";
    }

    if (foobar() !== 1)
        throw "Outer foobar was overwritten by inner!";
} 

This opens a block and defines a function foobar inside. It calls that function to asserts its return. Then it opens another block and again defines a function foobar there. This inner function "shadows" the outer one, as we can see on its return assertion. Then the inner block closes, and the outer foobar gets visible again.

Mind that the outer foobar would be available in the inner block if there wouldn't be another foobar!

Summary

ES6 comes closer to what is usual in programming languages than JS. Allowing to keep variables in block-scopes makes writing reusable code easier. Providing constants helps to avoid code corruption. The biggest difficulty for our eyes may become the similarity between object declarations and code blocks.




Sonntag, 12. November 2017

Test ES6 Support in Browsers

So we got a new programming language that builds on bad old JavaScript! It is called EcmaScript, and I wrote about it more than a year ago in this Blog. Most future web browsers already support it. Current version is 6, so it's called ES6, alias ES2015 (the year of specification, ES5 was in 2009). Any JS code is valid ES6 code, but not any ES6 code is valid JS code.

We will have to learn to read ES6, because it definitely is more complex than JS. Thus I am going to write several articles about the available ES6 features.

This Blog is about how to find out, in a web page, whether the displaying browser supports ES6. Mind that the free Babel JS library can teach old browsers to interpret ES6 (although free, it may be a little expensive:-).

Test for ES6

There is a web page that recommends how you can test the browser's ES6 capability via traditional JavaScript:

Here you can see what new Function("(a = 0) => a") says about your browser:

Is ES6 fully supported by this browser?

(Here should be "Yes" or "No"!)

HTML

  <h4>Is ES6 fully supported by this browser?</h4>
  <h4 id="supportsES6">(Here should be "Yes" or "No"!)</h4>
  <p id="error"></p>

JS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<script>

  (function() {
    var error;

    /* From https://gist.github.com/bendc/d7f3dbc83d0f65ca0433caf90378cd95 */
    var supportsES6 = (function() {
      try {
        new Function("(a = 0) => a");
        return true;
      }
      catch (e) {
        error = e;
        return false;
      }
    }());
    
    var color = supportsES6 ? "Green" : "Red";
    var label = supportsES6 ? "Yes!" : "No!";
    var messageText = supportsES6 ? "" : error;

    var indicator = document.getElementById("supportsES6");
    indicator.style.color = color;
    indicator.innerHTML = label;
        
    var message = document.getElementById("error");
    message.innerHTML = messageText;
  }());
  
</script>

The Thing with the Semicolon

Here comes a small foretaste of ES6 features. (If you have problems reading that source, don't care, I will explain it in my next Blog.)

You remember that ES6 discourages the use of semicolons as statement separator?

I could say now that no browser at all already supports ES6. Look at following script. You can find it among the "Destructuring Assignment" examples on the ES6 feature-page. This failed on all browsers I tried (Chrome, Firefox, Opera).

   var toggleVariableValues = function() {
     let [ a, b ] = [ 1, 2 ] /* error when no semicolon here! */
     [ b, a ] = [ a, b ]
     if (a !== 2 || b !== 1)
       throw "Toggling variable values failed!"
   };

Try it out here (maybe it's already fixed?):


The specification says following:

Certain ECMAScript statements (empty statement, let, const, import, and export declarations, variable statement, expression statement, debugger statement, continue statement, break statement, return statement, and throw statement) must be terminated with semicolons.
....
For convenience, however, such semicolons may be omitted from the source text in certain situations.
....

I don't believe that I'm the only one with semicolon problems. I plead for always setting a semicolon, in JS and also in ES6. Or do we want to study when to set and when not?




Sonntag, 5. November 2017

Setting up a Minimal Java Servlet Application

There is an HTML element named FORM that provides interactivity with the web-server the page comes from, without having to use JavaScript and AJAX. As soon as you use that element, you will want to have access to the web-server the page was loaded from, to see what was sent to the server on submit, and maybe program what should be the response. This is the world of the HTTP protocol. Using the FORM element you move from a web page to a web application.

This Blog is about setting up a minimal web server. Intent is to see what the browser-client FORM sends, and maybe to provide a response. I will use the the platform-independent language Java, the Java project-management tool Maven, the Java web server Jetty, and the Java servlet specification to do that.

Creating a Webapp Skeleton via Maven

After installing Java and Maven, open a command input window and enter

mvn -version

to test it. When it is not available, you may need to put $MAVEN_HOME/bin into your operating system path, where $MAVEN_HOME is the directory you unpacked Maven into.

Now change to a directory where your servlet project can reside, and enter following Maven command line:

cd my-projects

mvn archetype:generate \
  -DarchetypeArtifactId=maven-archetype-webapp \
  -DgroupId=my.web.examples \
  -DartifactId=simplewebapp \
  -DinteractiveMode=false

This will generate a directory simplewebapp in current directory, and create files and directories below it that represent the server-side of a web-application, managed by Maven. Any Java IDE like Eclipse, NetBeans or Idea should be able to support such a directory structure.

The groupId and artifactId are part of the Maven "coordinates", you will find them again inside the generated pom.xml file. The version will be set to 1.0-SNAPSHOT by default. When not having interactiveMode=false, Maven will prompt you to input configurations.

Maven chooses the artifactId (simplewebapp) to be the name of the directory it creates for the application.

simplewebapp
pom.xml
src
main
resources
webapp
index.jsp
WEB-INF
web.xml

Herein are only three files:

  1. The pom.xml file is the Maven project maintenance file.

    <project
        xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>my.web.examples</groupId>
      <artifactId>simplewebapp</artifactId>
      <version>1.0-SNAPSHOT</version>
    
      <packaging>war</packaging>
    
      <dependencies>
      </dependencies>
    
      <build>
        <finalName>simplewebapp</finalName>
      </build>
    
    </project>
    

    Mind that I removed the now unneeded dependency to JUnit (Java test framework), and some other unneeded elements.

  2. The index.jsp file is what you will see when the servlet is running that we are about to build. The extension ".jsp" refers to Java Server Pages, one of the oldest web application frameworks. A JSP file is a mix of HTML and JSP tags, so you always can put HTML into it.

    <html>
      <body>
        <h2>Hello World!</h2>
      </body>
    </html>
    
  3. The web.xml file finally is the servlet deployment descriptor. There can be several servlets. When you drop a packed .war file ("web archive", containing a web.xml) into the the deployment-directory of a servlet container, it will load the web-app from the archive using WEB-INF/web.xml.

    <!DOCTYPE web-app PUBLIC
     "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
     "http://java.sun.com/dtd/web-app_2_3.dtd" >
    
    <web-app>
      <display-name>Archetype Created Web Application</display-name>
    </web-app>
    

Running the Web App

Before we can test the application, we need to tell Maven to download Jetty. This is a lightweight HTTP-server for development and test, not suited for production.

In the <build> section of the Maven pom.xml, add the Jetty plugin:

  <build>
    <finalName>simplewebapp</finalName>
    <!-- This would produce a simplewebapp.war on "mvn package" -->
    
    <plugins>
      <plugin>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-maven-plugin</artifactId>
        <version>9.4.7.v20170914</version>
        <configuration>
          <scanIntervalSeconds>2</scanIntervalSeconds>
          <webApp>
            <contextPath>/simplewebapp</contextPath>
          </webApp>
          <httpConnector>
            <port>8080</port>
          </httpConnector>
        </configuration>
      </plugin>

    </plugins>
    
  </build>

Mind that we need to configure the web-application's context-path ("/simplewebapp"). The plugin will listen on port 8080 for HTTP requests. The port element is not required, as 8080 is the org.eclipse.jetty default port.

Now Maven is ready to run the web application. There is no servlet yet inside, but we should see index.jsp.

Change into the directory simplewebapp and run following Maven command line.

cd simplewebapp
mvn jetty:run

In case Maven tells you "[INFO] Started Jetty server", try to enter this URL into the address line of a new browser tab:

You should see this output from index.jsp:

You can shutdown the running Jetty server by typing Ctl-C on the command window.

Adding a Servlet

Before we can add a servlet, we need to tell Maven the dependency to the servlet-specification. Inside the <dependencies> section in pom.xml, add following lines:

  <dependencies>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

Now create following new directories, and add the SimpleServlet.java source file.

simplewebapp
src
main
java
my
web
examples
SimpleServlet.java

Put following content into it. It is a servlet by extending HttpServlet, which comes with the added servlet dependency.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package my.web.examples;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
 
public class SimpleServlet extends HttpServlet
{
  private int requestNumber;
  
  @Override
  public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException
  {
    printRequest("doGet", request, response);
  }
 
  @Override
  public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException
  {
    printRequest("doPost", request, response);
  }

  private void printRequest(String httpMethodName, HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException
  {
    requestNumber++;
    String page =
        "<!DOCTYPE html><html><body>\n"+
        "<p>SimpleServlet "+httpMethodName+
        "(), request "+requestNumber+
        " is:</p>\n<pre>"+request+
        "</pre>\n</body></html>";
    PrintWriter out = response.getWriter();
    out.println(page);
    out.flush();
    out.close();
  }
}

Now edit web.xml and configure the Java source as a servlet-class.

<web-app>
  <display-name>My Simple Servlet</display-name>
  
  <servlet>
    <servlet-name>uniqueServletName</servlet-name>
    <servlet-class>
      my.web.examples.SimpleServlet
    </servlet-class>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>uniqueServletName</servlet-name>
    <url-pattern>/simple-servlet</url-pattern>
  </servlet-mapping>
  
</web-app>

In the command window, start Jetty again by typing

mvn jetty:run

Enter this URL into the address line of a new browser tab (no trailing slash!):

You should see this:

You could remove index.jsp now if you want. The servlet does not depend on it.

Summary

Having a servlet running, we can let it display a HTML form element, and watch what is coming back when we submit that form. But to debug the servlet, we would need to attach an IDE to simplewebapp. May be subject to further Blog articles.

Mind that servlets are a very low level of web programming. You would end up in a complex mixture of HTML, Java, CSS and JavaScript. Prefer JSP, or any other framework like JSF.