Outils du site

La guerre, un massacre de gens qui ne se connaissent pas, au profit de gens qui se connaissent et ne se massacrent pas. [Paul ValérY]

56-tools:javascript

javascript

références

http://developer.mozilla.org/

http://www.javascriptkit.com/

http://www.nczonline.net/writing/

Doub Crockford “an inner function always has access to the vars and parameters of its outer function, even after the outer function has returned

http://2ality.com/2011/04/modules-and-namespaces-in-javascript.html

ES6

ECMAScript 2015 == ECMAScript 6

features

Exploring ES6

This & self

“If you want to access the this value of the outer function, you need to store that value into a variable that is in scope for the inner function. It is common to use the variable self for this purpose.” This is a workaround for an error in the ECMAScript Language Specification which causes this to be set incorrectly for inner functions.

var objA = {
   test : function() {
      var self = this;
      isObject();
      function isObject() {
	console.log('this === objA: '+(this === objA));
	console.log('self === objA: '+(self === objA));
      }
   }
}
objA.test();
// this === objA: false
// self === objA: true

Avoid globals

“Global variables and function names are an incredibly bad idea. The reason is that every JavaScript file included in the page runs in the same scope.” http://dev.opera.com/articles/javascript-best-practices/

Instead of

var current = null;
function init() {
	…
}
function change() {
	…
}
function verify() {
	…
}

Prefer:

myNameSpace = function() {
	var current = null;
	function init() {
		…
	}
	function change() {
		…
	}
	function verify() {
		…
	}
	return{
		init:init,
		set:change
	}
}();

Calling myNameSpace.set() will now invoke the change() method.

Bind

“The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.” https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

// Example showing binding some parameters
var sum = function(a, b) {
  return a + b;
};

var add5 = sum.bind(null, 5);
console.log(add5(10));

Closure

source: https://stackoverflow.com/questions/111102/how-do-javascript-closures-work

“In JavaScript, if you use the function keyword inside another function, you are creating a closure.”

“A closure in JavaScript is like keeping a copy of all the local variables, just as they were when a function exited.”

Two one sentence summaries:

  • a closure is one way of supporting first-class functions; it is an expression that can reference variables within its scope (when it was first declared), assigned to a variable, passed as an argument to a function, or returned as a function result.
  • Or a closure is a stack frame which is allocated when a function starts its execution, and not freed after the function returns (as if a 'stack frame' were allocated on the heap rather than the stack!).

The following code returns a reference to a function:

function sayHello2(name) {
    var text = 'Hello ' + name; // Local variable
    var say = function() { console.log(text); }
    return say;
}
var say2 = sayHello2('Bob');
say2(); // logs "Hello Bob"
// closure example
function makeAdder(x) {
  return function(y) {
    return x + y;
  };
}

var add5 = makeAdder(5);
var add100 = makeAdder(100);

console.log(add5(2));  // 7
console.log(add100(2)); // 102

Closure in loop:

for ( var d = 0; d < 3; d++ ) (function(d){ 
 setTimeout(function(){ 
   console.log( "Value of d: ", d ); 
   console.log( d == d, "Check the value of d." ); 
 }, d * 200); 
})(d);

IIFE

IIFE (Immediately Invoked Function Expression) is a JavaScript function that runs as soon as it is defined.

// Syntaxe 1:
(function foo() {
    console.log("Hello");
}());

// Syntaxe 2:
(function foo() {
    console.log("Hello");
})();

Exemple :

var namespace = namespace || {}

// here a namespace object is passed as a function
// parameter, where we assign public methods and
// properties to it
;(function( o ) {
	let privateVar = "bla bla" // Private
	o.foo = "foo"
	o.speak = function() {
		return privateVar
	};
})( namespace )

console.log( namespace ); // { foo: 'foo', speak: [Function] }
console.log( namespace.speak() ); // bla bla
console.log( namespace.foo ); // foo

http://tobyho.com/2011/11/02/callbacks-in-loops/

Public & Private methods

var myObject = (function() {
  var privateVar = '';

  function privateMethod () {
    // ...
  }

  return { // public interface
    publicMethod: function () {
      // all private members are accesible here
    },
  };
})();

Privileged method

// A privileged method is able to access the private variables and methods, and is itself accessible to the public methods and the outside. It is possible to delete or replace a privileged method, but it is not possible to alter it, or to force it to give up its nbrs.
//
// Privileged methods are assigned with this within the constructor.

function Container(param) {
   this.data = param;
   var self = this;
   var nbr = 3;
   var dec = function () {
      if (nbr > 0) {
         nbr -= 1;
         return true;
      } else {
	 return false;
      }
   }
   this.service = function () {
      return dec() ? self.data : null;
   };
}

var c = new Container('voila');
console.log(c.service()); // voila
console.log(c.service()); // voila
console.log(c.service()); // voila
console.log(c.service()); // null

Promise

The Promise object is used for asynchronous computations. A Promise represents a value which may be available now, or in the future, or never.

“Promises are not callbacks. A promise represents the future result of an asynchronous operation” … “Yes, Promises are asynchronous callbacks. They can't do anything that callbacks can't do, and you face the same problems with asynchrony as with plain callbacks.” stackoverflow

“Promises are containers for future values. When the promise receives the value (it is resolved) or when it is cancelled (rejected), it notifies all of its “listeners” who want to access this value.” stackoverflow

function delay() {
   // `delay` returns a promise
   return new Promise(function(resolve, reject) {
      // Only `delay` is able to resolve or reject the promise
      setTimeout(function() {
         resolve('That\s all folks!'); // After 0.3 seconds, resolve the promise with value 42
      }, 300);
   });
}

delay() // `delay` returns a promise
.then(function(v) { 
   console.log('done: '+v); // Log the value once it is resolved
})
.catch(function(v) {
   // (it would not happen in this example, since `reject` is not called).
   console.log('rejected: '+v); // Log the value once it is resolved
});

The callback approach is called an “inversion of control”. A function that accepts a callback instead of a return value is saying, “Don’t call me, I’ll call you.”. Promises un-invert the inversion, cleanly separating the input arguments from control flow arguments. This simplifies the use and creation of API’s, particularly variadic, rest and spread arguments.

promise library

lodash & underscore

Underscore is a JavaScript library that provides a whole mess of useful functional programming helpers without extending any built-in objects. It’s the answer to the question: “If I sit down in front of a blank HTML page, and want to start being productive immediately, what do I need?”

lodash A modern JavaScript utility library delivering modularity, performance & extras. C'est un fork de undescore avec plein d'améliorations en terme de performance, de lisibilité et de documentation.

Generator: function *

The function* declaration (function keyword followed by an asterisk) defines a generator function, which returns a Generator object. Generators are functions which can be exited and later re-entered. Their context (variable bindings) will be saved across re-entrances. [ES6]

Un générateur est une fonction particulière (function *) qui se met en pause (mot clé yeld) et reprend son exécution à la demande (appel de sa fonction next()). Il ne peut pas être réinitialisé depuis l'extérieur. Il conserve son contexte.

Un générateur peut aussi recevoir des valeurs lors de l'appel de next().

Remarque: on peut avoir ou pas un espace avant ou après le * qui suit le mot clé function.

'use strict';
function* idMaker(){
  var index = 0;
  while(true)
    yield index++;
}
var gen = idMaker();
console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2

// Ecriture condensée :

var getID = (function * (){
  var index = 0;
  while(true)
    yield index++;
})();
console.log(getID.next().value); // 0
console.log(getID.next().value); // 1
console.log(getID.next().value); // 2
  • Le generateur est appelé par sa fonction next()
  • yeld : stoppe le générateur et retourne un object {value: 'what you want', done: boolean} :
    • value: la valeur
    • done: true/false

http://gajus.com/blog/2/the-definitive-guide-to-the-javascript-generators

Exemple complexe: https://davidwalsh.name/es6-generators

// https://davidwalsh.name/es6-generators

// The first next(..) call, we don't send in anything. Why? Because there's no yield expression to receive what we pass in.
// The yield (x + 1) is what sends out value 6.
// The second next(12) call sends 12 to that waiting yield (x + 1) expression, so y is set to 12 * 2, value 24.0 Then the subsequent yield (y / 3) (yield (24 / 3)) is what sends out the value 8.
// The third next(13) call sends 13 to that waiting yield (y / 3) expression, making z set to 13.

function *foo(x) {
    var y = 2 * (yield (x + 1));
    var z = yield (y / 3);
    return (x + y + z);
}

var it = foo( 5 ); //  --> x = 5

// note: not sending anything into `next()` here
console.log( it.next() );    // { value:6, done:false } --> return 5 + 1 = 6
console.log( it.next(12) );  // { value:8, done:false } --> y = 24, return 12 * 2 / 3
console.log( it.next(13) );  // { value:42, done:true } --> z = 13, return 5 + 24 + 13
console.log( it.next() );    // { value: undefined, done: true }

Tests scripts web: fiddle

Tests scripts web: jsbin

Scritps

Pour afficher le code source d'une page web, tapez le code ci-dessous dans la barre d'adresse d'un navigateur :

javascript:x=document.body.innerHTML.replace(/</g,'&lt;').replace(/\n/g,'<br>'); document.body.innerHTML = x;

Attention: lors de la copie de ce code, souvent le navigateur enlève le “javascript:”. Il faut alors le remettre à la main.

Parcourir le DOM

function walkTheDOM(node, callback) {
    callback(node);
    node = node.firstChild;
    while (node) {
        walkTheDOM(node, callback);
        node = node.nextSibling;
    }
    
}

// Example usage: Process all Text nodes on the page
walkTheDOM(document.body, function (node) {
    console.log ("nodeType: " +node.nodeType + ", nodeName: " + node.nodeName + ", textContent: " + node.textContent);
});

Image encodée en CSS

Il très performant d'encoder les images souvent utilisées dans la CSS.

<style>
  .ImgCollapsed {
    cursor: pointer;
    width:20; height:20;
    text-decoration: none; 
    content: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAQCAYAAAD52jQlAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwQAADsEBuJFr7QAAABh0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC42/Ixj3wAAAOlJREFUOE+tkCESwjAQRVcgEIhKRAUSgewhEByCQyCQOI7AETgCAoFAcgQEEoFAIBCI8FOS7k8mQzIDnXnT37y/O23FGPN3NIjULGJyntEgsgJbloz3oEp5RsNnyIYLaLhU4hkNOmR5gWVQzHhGQ/gmfngPhiWeSS219xm4uecrmIKvPruUzg7uzHJ099bjqgH7Nei1jhaklu7cmSVeWgH2+aW4/L+7g/jzGxB4v6ed7YIOncCT8qjEM6mlnk1QTHjQ507X7YLIwpUfYM6lEs9oQBGcwYQLpZ7RIDJmEWM9GKRcTPLwN4y8AfxNottsD8mSAAAAAElFTkSuQmCC");
  }
</style>

<img class="ImgCollapsed" src=""  onclick="doSomething()"  title="Open"  />

Créer un tableau en Javascript

var table = document.createElement('table');
var row = table.insertRow();
row.insertCell().appendChild(document.createTextNode(nbModules));
row.insertCell().appendChild(document.createTextNode(nbSequences));
row.insertCell().appendChild(document.createTextNode(nbSeances));
var header = table.createTHead().insertRow();
header.insertCell().appendChild(document.createTextNode("Modules"));
header.insertCell().appendChild(document.createTextNode("Sequences"));
header.insertCell().appendChild(document.createTextNode("Seances"));
// Add the table to the containing element.
document.getElementById(elt).appendChild(table);
Dernière modification : 2018/01/20 02:59