Category Archives: JavaScript

JavaScript 78 – Tutto sulla programmazione nel browser – 2

Continuo da qui.

The dream behind the Web is of a common information space in which we communicate by sharing information. Its universality is essential: the fact that a hypertext link can point to anything, be it personal, local or global, be it draft or highly polished.
Tim Berners-Lee.

Ottima cit. per iniziare il capitolo su HTTP 😊
Poi Marijn spiega bene il protocollo HTTP, i messaggi che intercorrono tra te e il server e poi si arriva al browser con le URLs. Seguono XML, le request con sandox e le pomises. Infine un accenno alla sicurezza, argomento che andrebbe ampliato. Ma per intanto HTTPS.
Insomma un capitolo tutto da leggere e roba di tutti i giorni per tanti programmatori 😎

Intanto io passo al prossimo capitolo, le forms (le finestre di dialogo), per esempio


Le forms hanno diversi tipi di campi che vengono esaminati in dettaglio, per esempio

Ci sarebbero gli esercizi (Life di Conway) ma passo al prossimo capitolo, è un esercizio: A Paint Program per fare cose come questa:


Tanto JavaScript, da inserire in una pagina HTML. Per intanto pausa, poi si passerà a Node.js 😎

:mrgreen:

JavaScript 77 – Tutto sulla programmazione nel browser – 1

Continuo da qui.

Il progetto di un gioco nel browser
My initial fascination with computers, like that of many kids, originated with computer games. I was drawn into the tiny computer-simulated worlds that I could manipulate and in which stories (sort of) unfolded—more, I suppose, because of the way I could project my imagination into them than because of the possibilities they actually offered.

Comincia così il prossimo capitolo di Marijn 🚀 e continua dicendo:

This chapter will walk through the implementation of a simple platform game. Platform games (or “jump and run” games) are games that expect the player to move a figure through a world, which is often two-dimensional and viewed from the side, and do lots of jumping onto and over things.

E il gioco lo fa tutto e rockz 🚀 tutto da giocarci 😊 e studiarlo se si vuole approfondire JavaScript e diventare very über nerd 😊

Siccome è troppo specifico non lo copio, vedetelo di là.

Anche il capitolo successivo, disegnare sul canvas è specialistico; siccome riguarda solo il browser lo vedete di là, vero? 😎

Ebbene sì, sono giunto a qualcosa fuori dal mio mondo, anche se non si è interessati a programmare per il browser sono cose da leggere, perché si usano continuamente. E ormai i nuovi sono tutti sul Web (OK, quasi). Pausa, devo leggere anch’io 😯

:mrgreen:

JavaScript 76 – gestione degli eventi (nel browser)

Continuo da qui, copio qui.

Some programs work with direct user input, such as mouse and keyboard interaction. The timing and order of such input can’t be predicted in advance. This requires a different approach to control flow than the one we have used so far.

, quasi tutti i programmi funzionano così. Fanno eccezione i comandi da terminale e pochi altri. Qui, seguendo Marijn, qualche cenno, sempre relativo al browser.

Gestori di eventi
Imagine an interface where the only way to find out whether a key on the keyboard is being pressed is to read the current state of that key. To be able to react to keypresses, you would have to constantly read the key’s state so that you’d catch it before it’s released again. It would be dangerous to perform other time-intensive computations since you might miss a keypress.

That is how such input was handled on primitive machines. A step up would be for the hardware or operating system to notice the keypress and put it in a queue. A program can then periodically check the queue for new events and react to what it finds there.

Of course, it has to remember to look at the queue, and to do it often, because any time between the key being pressed and the program noticing the event will cause the software to feel unresponsive. This approach is called polling. Most programmers avoid it whenever possible.

A better mechanism is for the underlying system to give our code a chance to react to events as they occur. Browsers do this by allowing us to register functions as handlers for specific events.

The addEventListener function registers its second argument to be called whenever the event described by its first argument occurs.

Segue una lunga lezione, esaustiva, che non riporto. Al solito –mi ripeto– sto solo vedendo il linguaggio JavaScript per apprenderne le basi. Riporto solo le conclusioni di Marijn 🚀

Event handlers make it possible to detect and react to events we have no direct control over. The addEventListener method is used to register such a handler.

Each event has a type ("keydown", "focus", and so on) that identifies it. Most events are called on a specific DOM element and then propagate to that element’s ancestors, allowing handlers associated with those elements to handle them.

When an event handler is called, it is passed an event object with additional information about the event. This object also has methods that allow us to stop further propagation (stopPropagation) and prevent the browser’s default handling of the event (preventDefault).

Pressing a key fires "keydown", "keypress", and "keyup" events. Pressing a mouse button fires "mousedown", "mouseup", and "click" events. Moving the mouse fires “mousemove” and possibly "mouseenter" and "mouseout" events.

Scrolling can be detected with the "scroll" event, and focus changes can be detected with the "focus" and "blur" events. When the document finishes loading, a “load” event fires on the window.

Only one piece of JavaScript program can run at a time. Thus, event handlers and other scheduled scripts have to wait until other scripts finish before they get their turn.

:mrgreen:

JavaScript 75 – DOM – Document Object Model

Continuo da qui, copio qui.

When you open a web page in your browser, the browser retrieves the page’s HTML text and parses it. The browser builds up a model of the document’s structure and then uses this model to draw the page on the screen.

This representation of the document is one of the toys that a JavaScript program has available in its sandbox. You can read from the model and also change it. It acts as a live data structure: when it is modified, the page on the screen is updated to reflect the changes.

E di qui Marijn parte a raccontarci tutto (davvero tutto) sulla pagina HTML. Ottimo, da leggere ma non pertinente con questa serie (introduttiva) di JavaScirpt.

Per cui salto dopo riportando solo il

Riepilogo
JavaScript programs may inspect and interfere with the current document that a browser is displaying through a data structure called the DOM. This data structure represents the browser’s model of the document, and a JavaScript program can modify it to change the visible document.

The DOM is organized like a tree, in which elements are arranged hierarchically according to the structure of the document. The objects representing elements have properties such as parentNode and childNodes, which can be used to navigate through this tree.

The way a document is displayed can be influenced by styling, both by attaching styles to nodes directly and by defining rules that match certain nodes. There are many different style properties, such as color or display. JavaScript can manipulate an element’s style directly through its style property.

:mrgreen:

JavaScript 74 – il browser

Continuo da qui, copio qui.

The browser is a really hostile programming environment.
Douglas Crockford.

The next part of this book will talk about web browsers. Without web browsers, there would be no JavaScript. And even if there were, no one would ever have paid any attention to it.

Vero. Ma vero anche che a me interessa poco la visualizzazione nel browser, questa serie di posts sono introduttivi a JavaScript come linguaggio. Quindi riassumerò il post di Marijn.

Di là trovate una breve sintesi sulle reti, Internet, il TCP, il Web e infine il protocollo HTML.

Dentro il codice HTML ci possono essere script JavaScript, per esempio:

che eseguito nel browser produce:

Such a script will run as soon as its <script> tag is encountered as the browser reads the HTML.

Including large programs directly in HTML documents is often impractical. The <script> tag can be given an src attribute in order to fetch a script file (a text file containing a JavaScript program) from a URL.


The code/hello.js file included here contains the same simple program, alert("hello!"). When an HTML page references other URLs as part of itself, for example an image file or a script—web browsers will retrieve them immediately and include them in the page.

:mrgreen:

JavaScript 73 – progetto di un linguaggio di programmazione – 8

Continuo da qui, copio qui.

Aggiustare lo scope
Scope si potrebbe tradurre vita o visibilità o chissà come; io sono di una ‘gnuransa encyclopedica, si sa 😡

Currently, the only way to assign a variable a value is define. This construct acts as a way both to define new variables and to give existing ones a new value.

This ambiguity causes a problem. When you try to give a nonlocal variable a new value, you will end up defining a local one with the same name instead. (Some languages work like this by design, but I’ve always found it a silly way to handle scope.)

Add a special form set, similar to define, which gives a variable a new value, updating the variable in an outer scope if it doesn’t already exist in the inner scope. If the variable is not defined at all, throw a ReferenceError (which is another standard error type).

The technique of representing scopes as simple objects, which has made things convenient so far, will get in your way a little at this point. You might want to use the Object.getPrototypeOf function, which returns the prototype of an object. Also remember that scopes do not derive from Object.prototype, so if you want to call hasOwnProperty on them, you have to use this clumsy expression:

Object.prototype.hasOwnProperty.call(scope, name);

This fetches the hasOwnProperty method from the Object prototype and then calls it on a scope object.

Non ci sono riuscito (forse non mi sono applicato abbastanza); ho copiato qui
aggiungendo al file p-egg.js dei post precedenti il seguente codice:

specialForms["set"] = function(args, env) {
  if (args.length != 2 || args[0].type != "word")
    throw new SyntaxError("Bad use of set");
  var varName = args[0].name;
  var value = evaluate(args[1], env);

  for (var scope = env; scope; scope = Object.getPrototypeOf(scope)) {
    if (Object.prototype.hasOwnProperty.call(scope, varName)) {
      scope[varName] = value;
      return value;
    }
  }
  throw new ReferenceError("Setting undefined variable " + varName);
};

dopo l’ultima specialForms.
Ho poi creato il file scope.js:

require("./load.js") ("/p-egg.js");

run("do(define(x, 4),",
    "   define(setx, fun(val, set(x, val))),",
    "   setx(50),",
    "   print(x))");

run("set(quux, true)");

Eseguendolo però non ottengo quanto previsto, ecco il mio risultato

e quello atteso, di Marijn:

:mrgreen:

JavaScript 72 – progetto di un linguaggio di programmazione – 7

Continuo da qui, copio qui.
Sempre esercizi.

Commenti in Egg
It would be nice if we could write comments in Egg. For example, whenever we find a hash sign (#), we could treat the rest of the line as a comment and ignore it, similar to // in JavaScript.

We do not have to make any big changes to the parser to support this. We can simply change skipSpace to skip comments like they are whitespace so that all the points where skipSpace is called will now also skip comments. Make this change.

L’esercizio ha due aspetti: nodificare la regexp inserendo # e modificare il codice del linguaggio (p-egg.js) per cambiare la funzione skipSpace. Ma non ci sono riuscito. E non ho capito dove sbaglio, non ho trovato delucidazioni né su Stack Overflow né su Google. Sicuramente un errore mio ma non so quale.

La soluzione di Marijn, qui:

function skipSpace(string) {
  var skippable = string.match(/^(\s|#.*)*/);
  return string.slice(skippable[0].length);
}

console.log(parse("# hello\nx"));

console.log(parse("a # one\n   # two\n()"));

:mrgreen:

JavaScript 71 – progetto di un linguaggio di programmazione – 6

Continuo da qui, copio qui.
Continuo con gli esercizi.

Closure
The way we have defined fun allows functions in Egg to “close over” the surrounding environment, allowing the function’s body to use local values that were visible at the time the function was defined, just like JavaScript functions do.

The following program illustrates this: function f returns a function that adds its argument to f‘s argument, meaning that it needs access to the local scope inside f to be able to use variable a.

run("do(define(f, fun(a, fun(b, +(a, b)))),",
    "   print(f(4)(5)))");

Go back to the definition of the fun form and explain which mechanism causes this to work.

Uh! kwasy-panico 😯. Intanto creo il file clo.js inserendo nello script l’istruzione require, come già nell’esercizio del post precedente ed eseguo:

require("./load.js") ("/p-egg.js");

run("do(define(f, fun(a, fun(b, +(a, b)))),",
    "   print(f(4)(5)))");

OK, funziona 😎 La spiegazione del perché? cedo la parola a Marijn:

Again, we are riding along on a JavaScript mechanism to get the equivalent feature in Egg. Special forms are passed the local environment in which they are evaluated so that they can evaluate their subforms in that environment. The function returned by fun closes over the env argument given to its enclosing function and uses that to create the function’s local environment when it is called.

This means that the prototype of the local environment will be the environment in which the function was created, which makes it possible to access variables in that environment from the function. This is all there is to implementing closure (though to compile it in a way that is actually efficient, you’d need to do some more work).

:mrgreen:

JavaScript 70 – progetto di un linguaggio di programmazione – 5

Continuo da qui, copio qui.
Inizio con gli esercizi 😁

Arrays
Add support for arrays to Egg by adding the following three functions to the top scope: array(...) to construct an array containing the argument values, length(array) to get an array’s length, and element(array, n) to fetch the nth element from an array.

Non è banale, meglio sbirciare i suggerimenti:
The easiest way to do this is to represent Egg arrays with JavaScript arrays.

The values added to the top environment must be functions. Array.prototype.slice can be used to convert an arguments array-like object into a regular array.

Ecco il file egg-a.js:

require("./load.js") ("/p-egg.js");

topEnv["array"] = function() {
  return Array.prototype.slice.call(arguments, 0);
};

topEnv["length"] = function(array) {
  return array.length;
};

topEnv["element"] = function(array, i) {
  return array[i];
};

run("do(define(sum, fun(array,",
    "     do(define(i, 0),",
    "        define(sum, 0),",
    "        while(<(i, length(array)),",
    "          do(define(sum, +(sum, element(array, i))),",
    "             define(i, +(i, 1)))),",
    "        sum))),",
    "   print(sum(array(1, 2, 3))))");

Notare l’istruzione require che carica i moduli load.js e p-egg.js.
load.js è fornito da Marijn, ho modificato i path, questo:

// Since the code for most chapter in Eloquent JavaScript isn't
// written with node's module system in mind, this kludge is used to
// load dependency files into the global namespace, so that the
// examples can run on node.

module.exports = function() {
  for (var i = 0; i < arguments.length; i++)
    (1,eval)(require("fs").readFileSync(__dirname + arguments[i], "utf8"));
};

p-egg.js è il file costruito inserendo il codice definito nel progetto, questo:

function parseExpression(program) {
  program = skipSpace(program);
  var match, expr;
  if (match = /^"([^"]*)"/.exec(program))
    expr = {type: "value", value: match[1]};
  else if (match = /^\d+\b/.exec(program))
    expr = {type: "value", value: Number(match[0])};
  else if (match = /^[^\s(),"]+/.exec(program))
    expr = {type: "word", name: match[0]};
  else
    throw new SyntaxError("Unexpected syntax: " + program);

  return parseApply(expr, program.slice(match[0].length));
}

function skipSpace(string) {
  var first = string.search(/\S/);
  if (first == -1) return "";
  return string.slice(first);
}

function parseApply(expr, program) {
  program = skipSpace(program);
  if (program[0] != "(")
    return {expr: expr, rest: program};

  program = skipSpace(program.slice(1));
  expr = {type: "apply", operator: expr, args: []};
  while (program[0] != ")") {
    var arg = parseExpression(program);
    expr.args.push(arg.expr);
    program = skipSpace(arg.rest);
    if (program[0] == ",")
      program = skipSpace(program.slice(1));
    else if (program[0] != ")")
      throw new SyntaxError("Expected ',' or ')'");
  }
  return parseApply(expr, program.slice(1));
}

function parse(program) {
  var result = parseExpression(program);
  if (skipSpace(result.rest).length > 0)
    throw new SyntaxError("Unexpected text after program");
  return result.expr;
}

// console.log(parse("+(a, 10)"));

function evaluate(expr, env) {
  switch(expr.type) {
    case "value":
      return expr.value;

    case "word":
      if (expr.name in env)
        return env[expr.name];
      else
        throw new ReferenceError("Undefined variable: " +
                                 expr.name);
    case "apply":
      if (expr.operator.type == "word" &&
          expr.operator.name in specialForms)
        return specialForms[expr.operator.name](expr.args,
                                                env);
      var op = evaluate(expr.operator, env);
      if (typeof op != "function")
        throw new TypeError("Applying a non-function.");
      return op.apply(null, expr.args.map(function(arg) {
        return evaluate(arg, env);
      }));
  }
}

var specialForms = Object.create(null);

specialForms["if"] = function(args, env) {
  if (args.length != 3)
    throw new SyntaxError("Bad number of args to if");

  if (evaluate(args[0], env) !== false)
    return evaluate(args[1], env);
  else
    return evaluate(args[2], env);
};

specialForms["while"] = function(args, env) {
  if (args.length != 2)
    throw new SyntaxError("Bad number of args to while");

  while (evaluate(args[0], env) !== false)
    evaluate(args[1], env);

  // Since undefined does not exist in Egg, we return false,
  // for lack of a meaningful result.
  return false;
};

specialForms["do"] = function(args, env) {
  var value = false;
  args.forEach(function(arg) {
    value = evaluate(arg, env);
  });
  return value;
};

specialForms["define"] = function(args, env) {
  if (args.length != 2 || args[0].type != "word")
    throw new SyntaxError("Bad use of define");
  var value = evaluate(args[1], env);
  env[args[0].name] = value;
  return value;
};

var topEnv = Object.create(null);

topEnv["true"] = true;
topEnv["false"] = false;

var prog = parse("if(true, false, true)");
// console.log(evaluate(prog, topEnv));

["+", "-", "*", "/", "==", "<", ">"].forEach(function(op) {
  topEnv[op] = new Function("a, b", "return a " + op + " b;");
});

topEnv["print"] = function(value) {
  console.log(value);
  return value;
};

function run() {
  var env = Object.create(topEnv);
  var program = Array.prototype.slice
    .call(arguments, 0).join("\n");
  return evaluate(parse(program), env);
}

/*
run("do(define(total, 0),",
    "   define(count, 1),",
    "   while(<(count, 11),",
    "         do(define(total, +(total, count)),",
    "            define(count, +(count, 1)))),",
    "   print(total))");
*/

specialForms["fun"] = function(args, env) {
  if (!args.length)
    throw new SyntaxError("Functions need a body");
  function name(expr) {
    if (expr.type != "word")
      throw new SyntaxError("Arg names must be words");
    return expr.name;
  }
  var argNames = args.slice(0, args.length - 1).map(name);
  var body = args[args.length - 1];

  return function() {
    if (arguments.length != argNames.length)
      throw new TypeError("Wrong number of arguments");
    var localEnv = Object.create(env);
    for (var i = 0; i < arguments.length; i++)
      localEnv[argNames[i]] = arguments[i];
    return evaluate(body, localEnv);
  };
};

/*
run("do(define(plusOne, fun(a, +(a, 1))),",
    "   print(plusOne(10)))");

run("do(define(pow, fun(base, exp,",
    "     if(==(exp, 0),",
    "        1,",
    "        *(base, pow(base, -(exp, 1)))))),",
    "   print(pow(2, 10)))");
*/

Eseguo:

:mrgreen:

JavaScript 69 – progetto di un linguaggio di programmazione – 4

Continuo da qui, copio qui.
Post da vedersi come continuazione dei 3 precedenti 😎

Compilazione
What we have built is an interpreter. During evaluation, it acts directly on the representation of the program produced by the parser.

Compilation is the process of adding another step between the parsing and the running of a program, which transforms the program into something that can be evaluated more efficiently by doing as much work as possible in advance. For example, in well-designed languages it is obvious, for each use of a variable, which variable is being referred to, without actually running the program. This can be used to avoid looking up the variable by name every time it is accessed and to directly fetch it from some predetermined memory location.

Traditionally, compilation involves converting the program to machine code, the raw format that a computer’s processor can execute. But any process that converts a program to a different representation can be thought of as compilation.

It would be possible to write an alternative evaluation strategy for Egg, one that first converts the program to a JavaScript program, uses new Function to invoke the JavaScript compiler on it, and then runs the result. When done right, this would make Egg run very fast while still being quite simple to implement.

Ma no, non si fa, a meno che, dice Marijn: If you are interested in this topic and willing to spend some time on it, I encourage you to try to implement such a compiler as an exercise.

Copiare
When we defined if and while, you probably noticed that they were more or less trivial wrappers around JavaScript’s own if and while. Similarly, the values in Egg are just regular old JavaScript values.

If you compare the implementation of Egg, built on top of JavaScript, with the amount of work and complexity required to build a programming language directly on the raw functionality provided by a machine, the difference is huge. Regardless, this example hopefully gave you an impression of the way programming languages work.

And when it comes to getting something done, cheating is more effective than doing everything yourself. Though the toy language in this chapter doesn’t do anything that couldn’t be done better in JavaScript, there are situations where writing small languages helps get real work done.

Such a language does not have to resemble a typical programming language. If JavaScript didn’t come equipped with regular expressions, you could write your own parser and evaluator for such a sublanguage.

Or imagine you are building a giant robotic dinosaur and need to program its behavior. JavaScript might not be the most effective way to do this. You might instead opt for a language that looks like this:

behavior walk
  perform when
    destination ahead
  actions
    move left-foot
    move right-foot

behavior attack
  perform when
    Godzilla in-view
  actions
    fire laser-eyes
    launch arm-rockets

This is what is usually called a domain-specific language, a language tailored to express a narrow domain of knowledge. Such a language can be more expressive than a general-purpose language because it is designed to express exactly the things that need expressing in its domain and nothing else.

:mrgreen: