javascript tome iii

Transcription

javascript tome iii
J.B. Dadet DIASOLUKA Luyalu Nzoyifuanga
JA
V
ASCRIPT VOL. III
+243 - 851278216 - 899508675 - 991239212 - 902263541 - 813572818
La dernière révision de ce texte est disponible sur CD.
CHAPITRE 6 : Quelques notions importantes à savoir :
I. Portée du mode strict :
La portée du mode strict se limite à celle de l’élément SCRIPT ou
de la fonction dans lesquels ce mode a été activé.
<script type="text/javascript"> "use strict";
/////////
nondecl=45;
// ReferenceError:
// assignment to undeclared variable nondecl
</script>
<script type="text/javascript">
non_decl=50;
console.dir(non_decl) // 50
// "use strict" ne s’est pas étendu à cet élément.
function fstrict(){ "use strict";
/////////
nondecl=54;
// ReferenceError:
// assignment to undeclared variable nondecl
}
fstrict();
function freguliere(){
non_decl=500;
console.dir(non_decl) // 500
// "use strict" ne s’étend à cette fonction.
}
freguliere();
</script>
II. Classes en JavaScript :
Contrairement aux langages C/C++, JS ne possède pas les types de
données enum, structure...., et même les objets en JS ne sont pas des
classes comme dans C++. https://www.ecma-international.org/ecma-262/5.1
ECMAScript is object-based: basic language and host facilities are provided by objects, and an ECMAScript program is a cluster of communicating objects. An ECMAScript object is a collection of properties each with zero or more attributes that determine how each property can be used—for example, when the Writable attribute for a
property is set to false, any attempt by executed ECMAScript code to change the value
of the property fails. Properties are containers that hold other objects, primitive values,
or functions. A primitive value is a member of one of the following built-in types: Undefined, Null, Boolean, Number, and String; an object is a member of the remaining
built-in type Object; and a function is a callable object. A function that is associated
with an object via a property is a method.
ECMAScript defines a collection of built-in objects that round out the definition of ECMAScript entities. These built-in objects include the global object, the Object object,
the Function object, the Array object, the String object, the Boolean object, the Number object, the Math object, the Date object, the RegExp object, the JSON object, and
the Error objects Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError and URIError.
JS est un langage de programmation orienté objet (OOP) dans lequel TOUT sauf les valeurs primitives est objet (c’est-à-dire nativement doté ou pouvant à tout moment être doté de membres [ intrinsèques ] : propriétés représentant des valeurs et méthodes =
fonctions). Un membre particulier ou propriété particulière des objets JS c’est le prototype qui est une propriété au sens OOP figurant
une bibliothèque des propriétés héritables de l’objet en cours. Dans
certains langages de programmation les membres des objets
complexes (appelons ces objets « structures ») sont aussi appelés
« attributs ». Techniquement, en JavaScript « attribut » réfère à une
caractéristique particulière d’une propriété (attribute : internal value
that defines some characteristic of a property - https:/www.ecma-international.org/ecma-262/8.0).
Mais qui a dit que syntactiquement en JS les classes au look C++,
Smalltalk, ou Java (ou class-iques dit-on) n’existent pas, seuls les
objets et leurs prototypes ? Depuis le standard ECMAScript 2015
(ES6) JS dispose d’une syntaxe spéciale « class » permettant de plus
facilement créer des objets et manipuler leurs prototypes et donc
l’héritage.
En fait, class en JS est simplement une syntaxe spéciale pour définir
d’un coup un constructeur et les méthodes (pas les propriétés) de
son prototype. En réalité une class JS n’est ni plus ni moins une
fonction : il n’existe pas d’entité spécifique class en JavaScript.
J.D.B. DIASOLUKA Nz. Luyalu
2 / 16
JavaScript Tome-III
<script type="text/javascript"> "use strict";
let notreClass = class nomClasse {}
console.log(notreClass)
// function nomClasse()
[FIREFOX]
// class nomClasse {}
[YANDEX]
console.log(typeof notreClass)
// function
</script>
On introduit une définition de classe avec le mot clé « class », et le
constructeur d’une classe ne peut jamais être appelé sans « new ».
Par défaut, le constructeur d’une classe est une fonction vide.
Version class, sans prototype explicitement défini :
<script type="text/javascript"> "use strict";
class Person {
constructor(id) { this.id = id; }
congrat() {
console.log("Hello,",this.id);
// Hello, Brejnev.
}
}
let president = new Person("Brejnev.");
president.congrat();
</script>
Version objet : il faut définir explicitement le prototype.
<script type="text/javascript"> "use strict";
function Person(id) { this.id = id; }
Person.prototype.congrat = function() {
console.log("Hello,",this.id);
}
let president = new Person("Brejnev.");
// president hérite de la méthode congrat
// via le prototype.
president.congrat(); // Hello, Brejnev.
</script>
En fait, l’identifiant de la classe est aussi la fonction constructeur.
J.D.B. DIASOLUKA Nz. Luyalu
3 / 16
JavaScript Tome-III
<script type="text/javascript"> "use strict";
var vClass = class ClassName {
constructor(p) {
this.id=p;
};
fct(){console.log("Hello")}
}
console.log(vClass === vClass.prototype.constructor);
// true
console.log(
Object.getOwnPropertyNames(vClass.prototype));
// Array [ "constructor" , "fct" ]
</script>
Une classe JS possède, en plus des propriétés et méthodes comme
dans les objets, un constructeur.
Les corps des classes utilisent automatiquement le mode strict, le
corps des classes (pour les expressions et les déclarations de classes) est exécuté en mode strict (càd que la méthode constructeur,
les méthodes statiques, le prototype, les accesseurs [getters] et les
mutateurs [setters] sont exécutés en mode strict).
Les fonctions liées aux classes sont exécutées en mode strict quel
que soit le mode de JS.
Un « constructor » permet de créer et d'initialiser les objet. Lors de
la création d’un objet, l’objet lui-même est son propre constructeur.
Le constructeur d’une classe est explicite et doit être unique.
<script type="text/javascript"> "use strict";
class imc {
constructor(pds,tHt) {
this.icorp = pds / Math.pow(tHt,2);
}
}
let dias=new imc(60,1.65)
console.log(dias.icorp.toFixed(2),"kg/m2");
// 22.04 kg/m2
</script>
Exemple 2 : On peut utiliser une expression de classe.
Expression simple :
J.D.B. DIASOLUKA Nz. Luyalu
4 / 16
JavaScript Tome-III
<script type="text/javascript"> "use strict";
var Polygone = class {
constructor(longueur, largeur) {
this.nom = 'Polygone';
this.longueur = longueur/2;
this.largeur = largeur/2;
this.surf=(this.longueur*2)*(this.largeur*2);
this.qsurf=this.longueur*this.largeur;
}
}
let rect = new Polygone(10,15);
console.log("1/4 Surf=",rect.longueur*rect.largeur);
// 1/4 Surf= 37.5
console.log("1/4 Surf=",rect.qsurf);
// 1/4 Surf= 37.5
console.log("Surf=",rect.surf);
// Surf= 150
console.log("=========");
console.log(Polygone);
</script>
Ex
Exécution
cution :
test.html:12
22:17:18.784
22:17:18.784
22:17:18.784
22:17:18.784
1/4 Surf= 37.5
test.html:13 1/4 Surf= 37.5
test.html:14 Surf= 150
test.html:15 =========
test.html:16 class Polygone {}
Expression de classe, nommée : permet de faire référence à la
classe, au sein du corps de la classe. Ce nom de classe ne sera visible que du sein de la portée de l'expression de classe.
<script type="text/javascript"> "use strict";
var vClass = class ClassName {
constructor() {}
leNom() {
return ClassName.name;
}
}
var i = new vClass;
console.log(i.leNom());
// ClassName
///////// console.log(ClassName.name);
// ReferenceError: ClassName is not defined
console.log(vClass.name);
J.D.B. DIASOLUKA Nz. Luyalu
5 / 16
// ClassName
JavaScript Tome-III
</script>
Syntaxe générale :
var MaClasse = class [nomClasse] [extends] {
// corps de la classe
};
Le mot-clé « extends » (dans les déclarations ou les expressions de
classes) permet de créer une classe héritière d'une autre (« sousclasse » ou « classe-fille »).
<script type="text/javascript"> "use strict";
class Animal {
constructor(nom) {
this.nom = nom;
}
parle() {
return(this.nom + ' fait du bruit.');
}
}
class Chien extends Animal {
parle() {
return(this.nom + ' croque un os.');
// Chien hérite de « nom » dans Animal.
}
}
let iAnimal = new Animal("Milou");
console.log(iAnimal.parle());
// Milou fait du bruit.
let iChien = new Chien("Binky");
console.log(iChien.parle());
// Binky croque un os.
</script>
Les mots-clé « extends » et « super » :
<script type="text/javascript"> "use strict";
class Polygone {
constructor(hauteur, largeur) {
J.D.B. DIASOLUKA Nz. Luyalu
6 / 16
JavaScript Tome-III
this.nom = 'Polygone';
this.hauteur = hauteur;
this.largeur = largeur;
this.tSurf="Haut="+this.hauteur+
", Larg="+this.largeur
this.Surf=this.tSurf+" => "+
this.hauteur*this.largeur
}
calc(){ return "Surf "+
this.nom+": "+this.Surf }
}
class Carré extends Polygone {
constructor(longueur) {
super(longueur);
this.nom = 'Carré';
this.tSurf="Longueur="+longueur
this.Surf=this.tSurf+" => "+
Math.pow(longueur,2);
}
}
class Volume extends Carré {
constructor(longueur,largeur,hauteur) {
super(longueur,largeur,hauteur);
this.nom = 'Volume';
this.tVol="Haut="+hauteur+", Larg="+
largeur+", Long="+longueur
this.Vol=this.tVol+" => "+
longueur*largeur*hauteur;
}
calc(){return this.nom+": "+this.Vol}
}
let iPolyg = new Polygone(10,20);
console.log(iPolyg.calc());
// Surf Polygone: Haut=10, Larg=20 => 200
let iSurf = new Carré(17);
console.log(iSurf.calc());
// Surf Carré: Longueur=17 => 289
let iVol = new Volume(3,5,7);
console.log(iVol.calc());
// Volume: Haut=7, Larg=5, Long=3 => 105
</script>
J.D.B. DIASOLUKA Nz. Luyalu
7 / 16
JavaScript Tome-III
Appel d’une méthode du parent (super) à partir d’une classe fille :
<script type="text/javascript"> "use strict";
function Voiture (nom) {
this.nom = nom;
}
Voiture.prototype.roule = function () {
console.log(this.nom + ' file très vite.');
// Ferari file très vite.
}
class deRally extends Voiture {
roule() {
super.roule();
// Ferari file très vite (ligne 6).
console.log(this.nom + ' chancelle.');
// Ferari chancelle.
}
}
let v = new deRally('Ferari');
v.roule();
</script>
Prototype et « super » !
<script type="text/javascript"> "use strict";
var Voiture = {
roule() {
console.log(this.nom + ' file très vite.');
}
};
class deRally {
constructor(nom) {
this.nom = nom;
}
roule() {
super.roule();
console.log(this.nom + ' traîne.');
}
}
Object.setPrototypeOf(deRally.prototype, Voiture);
// Donne accès aux méthodes de Voiture.
J.D.B. DIASOLUKA Nz. Luyalu
8 / 16
JavaScript Tome-III
var d = new deRally('Ferari');
d.roule();
</script>
Les classes peuvent inclure des getters et des setters :
<script type="text/javascript"> "use strict";
class User {
constructor(idName) {
console.log("Ds constructor.");
this.idName = idName; // invoque le setter
}
get idName() {
console.log(this._idName,"- de get");
return this._idName;
}
set idName(value) {
console.log("Ds setter.");
if (value.length < 4) {
console.log("idName trop court.");
return;
}
this._idName = value;
}
}
console.log('Avant let user=new User("John")');
let user = new User("Jerry");
console.log('Avant [console.log(user.idName)]');
console.log(user.idName,"- direct"); // Jerry
console.log('Avant user=new User("")');
user = new User("Jerry"); // idName trop court.
console.log('The END!');
</script>
Ex
Exécution-trac
cution-trac
cution-tracée,
e, avec YANDEX
YANDEX:
:
00:08:22.781 test.html:23
Avant let user=new User("John")
00:08:22.784 test.html:4
Ds constructor.
00:08:22.784 test.html:14
Ds setter.
00:08:22.785 test.html:25
Avant [console.log(user.idName)]
00:08:22.785 test.html:9
Jerry - de get
00:08:22.785 test.html:26
Jerry - direct
00:08:22.786 test.html:28
Avant user=new User("")
00:08:22.786 test.html:4
Ds constructor.
00:08:22.786 test.html:14
Ds setter.
J.D.B. DIASOLUKA Nz. Luyalu
9 / 16
JavaScript Tome-III
00:08:22.787 test.html:30
The END!
« symbole.species » permet de surcharger le constructeur par défaut d’une méthode qui renvoie un objet Array avec une sousclasse par exemple MonArray e.g. la méthode map() , par exemple
pour modifier le format <du résultat.
<script type="text/javascript"> "use strict";
class MonArray extends Array {
static get [Symbol.species]() { return Object; }
// On surcharge species avec le constructeur Object
}
var a = new MonArray("2","4","6");
console.log(a instanceof MonArray); // true
var mapped = a.map(x => x * x);
console.log(mapped); // Number {3, 0: 4, 1: 16, 2:
36}
console.log(MonArray); // class MonArray extends Array {}
console.log(mapped
console.log(mapped
console.log(mapped
console.log(mapped
instanceof
instanceof
instanceof
instanceof
MonArray);
Array);
Object);
Number);
//
//
//
//
false
false
true
true
console.log("==========");
class MonArray2 extends Array {
static get [Symbol.species]() { return Array; }
// On surcharge species avec le constructeur Array
}
var a = new MonArray2("2","4","6");
var mapped = a.map(x => x * x);
console.log(mapped);// Array [ 4, 16, 36 ]
console.log(MonArray); // class MonArray extends Array {}
console.log(mapped instanceof MonArray2); // false
console.log(mapped instanceof Array);
// true
console.log(mapped instanceof Object);
// true
console.log(mapped instanceof Number);
// false
</script>
Ne confondez pas la méthode Array.map (qui permet d’appliquer un
même traitement à chaque membre d’une array) et l’objet Map (capitalisé) qui permet de créer un objet HashTable ou Dictionary. Ce
HashTable est comme un objet ordinaire avec des clés et des
valeurs associées, sauf qu’un Map peut utiliser comme clé n’importe
J.D.B. DIASOLUKA Nz. Luyalu
10 / 16
JavaScript Tome-III
quoi sauf les mots clés (numérique, string ou objet), alors que les
autres objets n’admettent que des strings comme clés. Pour accéder
aux clés Map utilise les méthodes « get » et « set »., alors que les
objets utilisent le point séparateur (objet.clé).
La clé d’un Map doit être soit un nombre (entre guillemets ou pas :
les deux sont distincts), soit une chaîne représenté un objet déjà
défini, ou alors une chaîne littérale (entre guillemets).
<script type="text/javascript"> "use strict";
let y = new Map(); // objet Map
y.set(2018, 'val de 2018');
y.set("25", 'val de 25');
y.set("z", 'val de "z"');
let x = new Map(); // objet Map
let objectKey = { key: 'keyvalue' }; // litt
d'objet.
console.log(objectKey); // Object { key: "keyvalue" }
console.log(objectKey.key); // keyvalue
console.log(x.get(objectKey)); // undefined
x.set(1, 'clé numérique');
console.log(x.get(1)); // clé numérique
x.set('1', 'clé string');
console.log(x.get('1')); // clé string
x.set('objk', objectKey);
console.log(x.get('objk'));
// Object { key: "keyvalue" }
x.set(objectKey, ['une', 'Array', 'comme', 'valeur']);
console.log(x.get(objectKey));
// (4) ["une", "Array", "comme", "valeur"]
console.log(objectKey.key); // keyvalue
let fv=function(){this.pr="Property"};
x.set(fv, 'objet expression de fonction');
console.log(x.get(fv));
// objet expression de fonction
console.log(y);
J.D.B. DIASOLUKA Nz. Luyalu
11 / 16
JavaScript Tome-III
// Map(3) {2018 => "val de 2018", "25" => "val de
25", "z" => "val de "z""}
x.set(y, 'Et même un autre objet Map');
console.log(x.get(y));
// Et même un autre objet Map
// L'objet Map clé ici n'altère pas
// l'objet Map de départ.
console.log(y);
// Map(3) {2018 => "val de 2018", "25" => "val de
25", "z" => "val de "z""}
// L'objet Map de départ n'a pas été altéré.
console.log(x);
// Map(6) {1 => "clé numérique", "1" => "clé
string", "objk" => {…}, {…} => Array(4), ƒ => "objet expression de fonction", …}
</script>
Création d’objet Map avec des itérables (array d’arrays ou un générateur) : new Map ( iterable : Object ).
<script type="text/javascript"> "use strict";
var obj_key = { prop: 'property' };
var fromArray = new Map(
[[0, 'array0'], [obj_key, 'array1']]);
// Initialisation de fromArray
// (nouvel objet Map)
// avec une itération d'arrays.
console.log(fromArray.get(0)); // array0
console.log(fromArray.get(obj_key)); // array1
console.log();
// Gnération d'entrées de Map
// avec une fonction génératrice.
var generator_fct = function*() {
yield [15, 'g15'];
yield [obj_key, 'gObK'];
};
// Initialisation de fromGenerator
// (nouvel objet Map)
// avec les entrées générées par un générateur.
J.D.B. DIASOLUKA Nz. Luyalu
12 / 16
JavaScript Tome-III
var fromGenerator = new Map(generator_fct());
// Affichage des entrées de fromGenerator.
console.log(fromGenerator.get(15)); // g15
console.log(fromGenerator.get(obj_key)); // gObK
console.log(fromGenerator.size); // 2
fromGenerator.set('add', 'value of add');
console.log(fromGenerator.size); // 3
fromGenerator.delete(15); // Retire
console.log(fromGenerator);
// Map(2) {{…} => "gObK", "add" => "value of
add"}
fromGenerator.clear(); // Efface tout
console.log(fromGenerator); // Map { }
</script>
Parcourons quelques propriétés de Map :
fromGenerator.hasOwnProperty() : false
fromGenerator.valueOf() : Map { 15 -> "g15", {…} ->
"gObK" }
fromGenerator.toString() : [object Map]"
fromGenerator.toSource() : "({})"
fromGenerator.size : 2
fromArray.has(0) : true
fromGenerator.has(15) : true
fromGenerator.has(150) : false
Le prototype de Map :
Map()
​ length: 0
​name: "Map"
​prototype: {…}
​clear: function clear()
​constructor: function Map()
​delete: function delete()
​entries: function entries()
​forEach: function forEach()
​get: function get()
​has: function has()
​keys: function keys()
​set: function set()
J.D.B. DIASOLUKA Nz. Luyalu
13 / 16
JavaScript Tome-III
​size: Getter
​values: function values()
​Symbol(Symbol.iterator): undefined
​Symbol(Symbol.toStringTag): undefined
​__proto__: Object { … }
​Symbol(Symbol.species): undefined
​__proto__: function ()
Map.entries() :
<script type="text/javascript"> "use strict";
var iMap = new Map(
[ [1, 'valueof 1'], ['s', 'valueof s'],
['9', 'valueof 9'] ]);
// BOUCLE FOR(...OF...) : Les entrées sont
// returnées par iMap[Symbol.iterator]
for (var value of iMap) { console.log(value); }
// Array [ 1, "valueof 1" ]
// Array [ "s", "valueof s" ]
// Array [ "9", "valueof 9" ]
// ITÉRATION EXPLICITE à travers les entrées
for (var value of iMap.values()) {
console.log(value);
}
// valueof 1
// valueof s
// valueof 9
for (var entry of iMap.entries()) {
console.log(entry);
}
// Array [ 1, "valueof 1" ]
// Array [ "s", "valueof s" ]
// Array [ "9", "valueof 9" ]
// PARCOURS MANUEL DE L'ITÉRATEUR
var entries = iMap.entries();
console.dir(entries.next());
console.dir(entries.next());
console.dir(entries.next());
console.dir(entries.next());
/*
J.D.B. DIASOLUKA Nz. Luyalu
14 / 16
JavaScript Tome-III
Object
done: false
value: (2) [1, "valueof 1"]
Object
done: false
value: (2) ["s", "valueof s"
Object
done: false
value: (2) ["9", "valueof 9"]
Object
done: true
value: undefined
*/
// ITÉRATION AVEC FOREACH
iMap.forEach(function(val, cle, obj) {
console.log(
'clé: "' + cle + '", val: "'
'+obj);
});
// clé: "1", val: "valueof 1" [object
// clé: "s", val: "valueof s" [object
// clé: "9", val: "valueof 9" [object
+ val + '"
Map]
Map]
Map]
// FOR (...OF...) pour parcourir l'itérateur
for(var cle of iMap.keys()) { console.log(cle); }
// 1 // s // 9
for(var val of iMap.values()) { console.log(val);
}
// valueof 1 // valueof s // valueof 9
// UN AUTRE ACCÈS MANUEL À L'ITÉRATEUR
var cles = iMap.keys();
console.log(cles.next());
console.log(cles.next());
console.log(cles.next());
console.log(cles.next());
// Object { value: 1, done: false }
// Object { value: "s", done: false }
// Object { value: "9", done: false }
// Object { value: undefined, done: true }
var vals = iMap.values();
J.D.B. DIASOLUKA Nz. Luyalu
15 / 16
JavaScript Tome-III
console.log(vals.next());
console.log(vals.next());
console.log(vals.next());
console.log(vals.next());
// Object { value: "valueof 1", done: false }
// Object { value: "valueof s", done: false }
// Object { value: "valueof 9", done: false }
// Object { value: undefined, done: true }
</script>
III. Remplacer des membres d’Array par d’autres :
<script type = "text/javascript"> "use strict";
// Remplacez tous les "Louis" par "Rose" et "Blue".
function suppress(parr, val) {
var i;
while ((i = parr.indexOf(val)) != -1) {
parr.splice(i, 1,"*ROSE*","*MAGENTA*");
}
return parr;
}
let arr=["Louis", "Delon", "Keriy", "Louis"]
let narr=suppress(arr, "Louis")
console.log(narr);
/*
FIREFOX & MAXTHON :
Array [ "*ROSE*", "*MAGENTA*", "Delon", "Keriy", "*ROSE*",
"*MAGENTA*" ]
OPERA :
(6) ["*ROSE*", "*MAGENTA*", "Delon", "Keriy", "*ROSE*",
"*MAGENTA*"]
YANDEX :
1. Array(6)
A
0:"*ROSE*"
B
1:"*MAGENTA*"
C
2:"Delon"
D
3:"Keriy"
E
4:"*ROSE*"
F
5:"*MAGENTA*"
*/
</script>
J.D.B. DIASOLUKA Nz. Luyalu
16 / 16
JavaScript Tome-III

Documents pareils