javascript tome xvii - Prototype en JavaScript

Transcription

javascript tome xvii - Prototype en JavaScript
L E P R O T O T Y P E e n JAVA / E C M A SCRIPTS
J AVA S C R I P T (Programmation Internet) V O L . V
Pour Débutants
J.B. Dadet DIASOLUKA Luyalu Nzoyifuanga
+243 - 851278216 - 899508675 - 991239212 - 902263541 - 813572818
La dernière révision de ce texte est disponible sur CD.
CHAPITRE 7 : LE PROTOTYPE :
ECMA définit le prototype comme ceci :
« object that provides shared properties for other objects ».
Le PROTOTYPE d’un objet est la propriété (méthode) native de cet
objet qui stocke toutes les valeurs par défaut des propriétés et méthodes
natives de cet objet en tant que parent, quand la propriété ou la méthode
n’est pas définie dans l’instance. Le prototype est initialement vide au
moment de la construction de l’objet. Pour définir des propriétés pour
cet objet ou lui en ajouter d’autres, il suffit de les ajouter via son prototype, et automatiquement ces nouvelles propriétés seront partagées avec
toutes les instances de cet objet. Bien entendu on peut aussi ajouter directement de nouvelles propriétés à l’objet ou l’une ou l’autre de ces
instances, tout simplement en omettant le mot prototype dans la définition de la nouvelle propriété, mais dans ce cas cette nouvelle propriété
de l’objet ne sera pas membre du prototype de l’objet et donc ne sera pas
héritable (ou partageable avec les instances), donc strictement personnel
à ce constructeur ou cette instance.
Précipitons un peu les choses, voyons d’emblée comment définir un prototype pour un objet :
<script type="text/javascript"> "use strict";
let t=" Object.setPrototypeOf()",
l=t.length+5,m=l+5;
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
console.log("".padStart(m,"*"));
console.log(t.padStart(l,"*").padEnd(m,"*"));
console.log("*".repeat(m));
var dObj = function(){};
console.log(dObj.prototype);
// Object { … }
//
constructor: function dObj()
//
<prototype>: Object { … }
// Deux Instanciations
let iObj1 = new dObj();
let iObj_1 = new dObj();
/* 1 */
// Instances iObjx [de dObj] n'ont pas encore de prototype.
// On doit leur en créer.
//
iObj1.prototype.fprot11= _=>
//-- FIREFOX:
TypeError:
//-iObj.prototype is undefined
////
//== YANDEX:
Uncaught TypeError:
//== Cannot set property 'fprot11' of undefined
//== at test.html:21
//
console.log("iObj1.prototype.fprot11");
console.log(iObj1.prototype);
//
undefined
console.log(Object.getPrototypeOf(iObj1));
// Avec Firefox:
// Object { … }
//
constructor: function dObj()
//
constructor: dObj()
//
length: 0
//
name: "dObj"
//
prototype: Object { … }
//
<prototype>: function ()
//
<prototype>: Object { … }
//
// Avec Yandex:
// {constructor: ƒ}
//
constructor: ƒ ()
//
arguments: (...)
//
caller: (...)
//
length: 0
//
name: "dObj"
//
prototype: {constructor: ƒ}
Le Prototype en Java/Ecma-Script
2 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
//
//
//
//
JavaScript Tome-V
__proto__: ƒ ()
[[FunctionLocation]]: test.html:8
[[Scopes]]: Scopes[2]
__proto__: Object
console.log(iObj1.prototype);
console.log(iObj_1.prototype);
// undefined
// undefined
/* 2 */
// AJOUT DE PROTOTYPE à L'INSTANCE iObj1 QUI
// n'en a pas encore cfr ci-haut.
function fprot1(){ Math.PI; }
Object.setPrototypeOf ( iObj1, fprot1);
// Le prototype de iObj1 n'est plus undefined:
console.log(iObj1.prototype);
// Object { … }
//
constructor: function fprot1()
//
<prototype>: Object { … }
// Le prototype de iObj_1 est toujours undefined:
console.log(iObj_1.prototype);
// undefined
/* 3 */
// Ajout propriété propre à l'instance iObj_1
iObj_1.fmetho = function(){
console.log("Ds iObj_1.fmetho");
}
iObj_1.fmetho(); // Ds iObj_1.fmetho
// La nouvelle méthode propre de iObj_1,
// iObj_1.fmetho() n'est Pas accessible à iObj1,
// [pourtant] soeur de iObj_1, instances de dObj.
// iObj1.fmetho();
// Avec Firefox: TypeError:
// iObj1.fmetho is not a function
//
// Avec Yandex : Uncaught TypeError:
// iObj1.fmetho is not a function
at test.html:60
</script>
Avec Firefox :
Le Prototype en Java/Ecma-Script
3 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
**********************************
test.html:4:3
Avec Yandex:
Le Prototype en Java/Ecma-Script
4 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
Ci-après, nous utiliserons une méthode simple de création de prototype.
<script type="text/javascript">
cl=console.log
obj_Const=function(pnom,pdaten){
this.K=1000*3600*24*365.2475;
this.nom=pnom;
this.daten=pdaten;
this.age=function(){
return((new Date()-pdaten)/this.K)
}
}
i=new obj_Const("André",new Date("August 1953 11"));
for(i in obj_Const.prototype)cl(i);
cl("Age = "+i.age());
cl("AJOUT DE PROTOTYPES")
obj_Const.prototype.riche=true; // Ajout via prototype
obj_Const.sage=false; // Ajout direct (ne se répand pas)
obj_Const.prototype.nbfemmes=35; // Ajout via prototype
obj_Const.prototype.polygame=function(){ // ---"--if(this.nbfemmes>1)return true;
Le Prototype en Java/Ecma-Script
5 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
else return false;
};
cl("LISTE DES PROPRIÉTÉS")
cl("i.nom="+i.nom);
cl("i.age="+i.age());
cl("i.sage="+i.sage);
cl("i.riche="+i.riche);
cl("i.nbfemmes="+i.nbfemmes)
cl("i.polygame="+i.polygame())
cl("\nLES PROTOTYPES AJOUTÉS")
for(i in obj_Const.prototype)
cl("==> "+i+" = "+obj_Const.prototype[i]);
cl(obj_Const.prototype);
cl(i.prototype);
cl(obj_Const.prototype.constructor);
cl(obj_Const.__proto__.constructor);
cl("obj_Const.prototype.constructor.length = "+
obj_Const.prototype.constructor.length);
</script>
Exécution :
Age = 64.3917223791744
AJOUT DE PROTOTYPES
LISTE DES PROPRIÉTÉS
i.nom=André
i.age=64.39172237923778
i.sage=undefined
i.riche=true
i.nbfemmes=35
i.polygame=true
LES
==>
==>
==>
PROTOTYPES AJOUTÉS
riche = true
nbfemmes = 35
polygame = function(){ // ---"--if(this.nbfemmes>1)return true;
else return false;
}
Object { riche: true, nbfemmes: 35, polygame:
obj_Const.prototype.polygame(), … }
Le Prototype en Java/Ecma-Script
6 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
undefined
function obj_Const()
function Function()
obj_Const.prototype.constructor.length = 2
Ajout d’un prototype à un objet :
<script type="text/javascript">
"use strict";
Array.prototype.remVal = function(val) {
console.log(["Louis", "Morena", "Keriyza", "Louis"]);
for (var i = 0, l=this.length; i < l; i++) {
if (this[i] === val) {
this.splice(i, 1);
i--;
}
}
return this;
}
console.log(["Louis", "Morena", "Keriyza", "Louis"].remVal(2));
</script>
Exécution :
(4) ["Louis", "Morena", "Keriyza", "Louis"]
(2) ["Morena", "Keriyza"]
Pour différents modes de création d’objet :
<script type="text/javascript">
"use strict";
/* 1 */
console.log(
"***AVEC CONSTRUCTEUR, var dObj = function(){}"
)
var dObj = function(){}
Le Prototype en Java/Ecma-Script
7 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
// Ce constructeur dObj a un prototype implicite
console.log(dObj.prototype);
// Avec FireFox : Object { … }
// Avec Yandex : {constructor: ƒ}
// {…}
//
constructor: function dObj()
//
fprot11: function fprot11()
//
fprot12: function fprot12()
//
fprot32: function fprot32()
//
fprot35: function fprot35()
//
<prototype>: Object { … }
console.log(Object.getPrototypeOf(dObj));
// Avec FireFox : Object { … }
// Avec Yandex : {constructor: ƒ}
// ()
//
apply: function apply()
//
arguments: null
//
bind: function bind()
//
call: function call()
//
caller: null
//
constructor: function Function()
//
length: 0
//
name: ""
//
toSource: function toSource()
//
toString: function toString()
//
Symbol(Symbol.hasInstance):
//
function Symbol.hasInstance()
//
<prototype>: Object { … }
// Création de deux instances distinctes de dObj.
var iObj1 = new dObj();
var iObj1_ = new dObj();
// Ajout de méthode au prototype du constructeur.
dObj.prototype.fprot11= _=>
console.log("dObj.prototype.fprot11");
// Appel à partir des instances, de nvelle méthode
// du prototype du constructeur.
iObj1.fprot11();
// dObj.prototype.fprot11
iObj1_.fprot11();
// dObj.prototype.fprot11
// Ajout de méthode au prototype du
Le Prototype en Java/Ecma-Script
8 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
// constructeur du costructeur
iObj1.__proto__.fprot12 = _=>
console.log("1a. Ds iObj1.__proto__.fprot12");
iObj1.fprot12(); // 1a. Ds iObj1.__proto__.fprot12
iObj1_.fprot12(); // 1a. Ds iObj1.__proto__.fprot12
// Nvelle méthode toujours disponible même à tous
// les descendants même de deuxième (et Xième) rang.
// L'instance iObj1 [de dObj] n'a pas encore de prototype.
// On doit lui en créer.
// iObj1.prototype.fprot11= _=>
//-- FIREFOX:
TypeError:
//-iObj.prototype is undefined
////
//== YANDEX:
Uncaught TypeError:
//== Cannot set property 'fprot11' of undefined
//== at test.html:12
//
console.log("iObj1.prototype.fprot11");
console.log(iObj1.prototype);
// undefined
console.log(dObj.prototype);
// Object { fprot11: fprot11(), fprot12: fprot12(), … }
console.log(Object.getPrototypeOf(dObj));
// function ()
//
apply: function apply()
//
arguments: null
//
bind: function bind()
//
call: function call()
//
caller: null
//
constructor: function Function()
//
length: 0
//
name: ""
//
toSource: function toSource()
//
toString: function toString()
//
Symbol(Symbol.hasInstance):
//
function Symbol.hasInstance()
//
<prototype>: Object { … }
// Ajout propriété propre à l’instance iObj1
// avec la méthode « Object.defineProperty() »
Object.defineProperty(iObj1, "fprot13", {
value:
Le Prototype en Java/Ecma-Script
9 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
function() {
console.log("1b. Ds iObj1.fprot13")
},
enumerable: false,
writable: false,
configurable: false
});
iObj1.fprot13(); // 1b. Ds iObj1.fprot13
// iObj1_.fprot13(); // Pas accessible
// [à partir iObj_1, instance jumelle de iObj].
// TypeError: iObj1_.fprot13 is not a function
console.log(iObj1_.fprot13); // undefined
/* 2 */
console.log(
"***AVEC NEW OBJECT(), var iObj2 = new Object()"
)
var dObj2 = new Object();
// dObj2 n'est un constructeur !
console.log(dObj2.prototype); // undefined
// Essai création d'instance de dObj2.
// Refus !
// var iObj2 = new dObj2();
// Firefox: TypeError: dObj2 is not a constructor
//
// Yandex : Uncaught TypeError:
// dObj2 is not a constructor
at test.html:83
// Enrichissement direct du prototype de dObj2.
// => Refus !
// dObj2.prototype.fprot21= _=>
// console.log("iObj2.prototype.fprot21");
// Firefox : TypeError: dObj2.prototype is undefined
//
// Yandex : Uncaught TypeError:
// Cannot set property 'fprot21' of undefined
//
at test.html:91
Le Prototype en Java/Ecma-Script
10 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
/* 3 */
console.log(
"***AVEC LITTERAL D'OBJET (HASH), var iObj3 = {}"
)
var dObj3 = {};
// Le constructeur dObj3 n'a pas de prototype natif
console.log(dObj3.prototype);
// undefined
// Création de deux instances distinctes de dObj3.
var iObj3 = new dObj();
var iObj3_ = new dObj();
// Enrichissement direct du prototype du constructeur.
// => Refus !
// dObj3.prototype.fprot31= _=>
//
console.log("iObj3.prototype.fprot31");
// Firefox : TypeError: dObj3.prototype is undefined
//
// Yandex : Uncaught TypeError:
// Cannot set property 'fprot31' of undefined
//
at test.html:119
// Ajout de méthode au prototype du
// constructeur du costructeur
iObj3.__proto__.fprot32 = _=>
console.log("3a. Ds iObj3.__proto__.fprot32");
iObj3.fprot32(); // 3a. Ds iObj3.__proto__.fprot32
iObj3_.fprot32(); // 3a. Ds iObj3.__proto__.fprot32
// Nvelle méthode toujours disponible même à tous
// les descendants même de deuxième (et Xième) rang.
// L'instance iObj3 [de dObj3] n'a pas encore de prototype.
// On doit lui en créer.
// iObj3.prototype.fprot33= _=>
// console.log("iObj2.prototype.fprot23");
//-- FIREFOX:
TypeError:
//-iObj3.prototype is undefined
////
Le Prototype en Java/Ecma-Script
11 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
//== YANDEX:
Uncaught TypeError:
//== Cannot set property 'fprot1' of undefined
//== at test.html:141
// Ajout propriété propre de l'instance iObj3
// (idem pour iObj3_)
iObj3.fprot34= function(){
console.log("3b. Ds iObj3.fprot34");
}
iObj3.fprot34(); // 3b. Ds iObj3.fprot34
iObj3_.fprot34= function(){
console.log("3c. Ds iObj3_.fprot34");
}
iObj3_.fprot34(); // 3c. Ds iObj3_.fprot34
// Enrichissement du prototype du constructeur
// du costructeur de l'instance iObj3.
iObj3.__proto__.fprot35 = _=>
console.log("3d. Ds iObj3.__proto__.fprot35");
iObj3.fprot35(); // 3d. Ds iObj3.__proto__.fprot35
iObj3_.fprot35(); // 3d. Ds iObj3.__proto__.fprot35
// Ajout de propriété (méthode) propre à l'instance iObj3
iObj3.fprot36= function(){
console.log("3e. Ds iObj3.fprot36");
}
iObj3.fprot36(); // 3e. Ds iObj3.fprot36
// iObj3_.fprot36();
// Avec Firefox : TypeError:
// iObj3_.fprot36 is not a function
//
// Avec Yandex : Uncaught TypeError:
// iObj3_.fprot36 is not a function
// at test.html:179
/* 4 */
Le Prototype en Java/Ecma-Script
12 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
console.log(
"***AVEC OBJECT.CREATE, let pObj = _ => {}"
)
let dObj4 = _ => {}
// Ce constructeur dObj n'a pas de prototype natif
console.log(dObj4.prototype); // undefined
// Création de deux instances distinctes de dObj.
let iObj4 = Object.create(dObj4);
let iObj4_ = Object.create(dObj4);
// Essai Ajout de méthode au prototype du constructeur.
// dObj4.prototype.fprot41= _=>
// console.log("dObj4.prototype.fprot41");
// Firefox: TypeError: dObj4.prototype is undefined
//
// Yandex : Uncaught TypeError:
// Cannot set property 'fprot41' of undefined
// at test.html:206
// Appel à partir des instances, de nvelle méthode
// du prototype du constructeur.
// iObj4.fprot41();
// iObj4_.fprot41();
// Firefox : TypeError:
// iObj4.fprot41 is not a function
//
// Yandex: Uncaught TypeError:
// iObj4.fprot41 is not a function
// at test.html:216
// Ajout de méthode au prototype du
// constructeur du costructeur
iObj4.__proto__.fprot42 = _=>
console.log("4a. Ds iObj4.__proto__.fprot42");
iObj4.fprot42(); // 4a. Ds iObj4.__proto__.fprot42
iObj4_.fprot42(); // 4a. Ds iObj4.__proto__.fprot42
// Nvelle méthode toujours disponible même à tous
// les descendants même de deuxième (et Xième) rang.
// L'instance iObj4 [de dObj4] n'a pas encore de prototype.
// On doit lui en créer.
// iObj4.prototype.fprot43= _=>
// console.log("iObj4.prototype.fprot43");
Le Prototype en Java/Ecma-Script
13 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
//-- FIREFOX:
TypeError:
//-iObj.prototype is undefined
////
//== YANDEX:
Uncaught TypeError:
//== Cannot set property 'fprot43' of undefined
//== at test.html:238
console.log(iObj4.prototype);
console.log(dObj4.prototype);
// undefined
// undefined
// Ajout propriété propre de la seule instance iObj4
iObj4.fprot44= function(){
console.log("4b. Ds iObj4.fprot44");
}
iObj4.fprot44(); // 4b. Ds iObj4.fprot44
console.log(iObj4_.fprot44); // undefined
</script>
console.log(Object.getOwnPropertyDescriptors(dObj4))
// Object { fprot42: {…}, length: {…}, name: {…} }
//
fprot42: Object {} AVEC FIREFOX
//
fprot42: Object {} AVEC YANDEX
Le Prototype en Java/Ecma-Script
14 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
//
name: Object
{}
AVEC FIREFOX
//
name: Object
{}
AVEC YANDEX
//
length: Object
{}
AVEC FIREFOX
//
length: Object
{}
AVEC YANDEX
Le Prototype en Java/Ecma-Script
15 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
//
prototype: Object {} AVEC FIREFOX
//
prototype: Object {} AVEC YANDEX
console.log(Object.getOwnPropertyDescriptors(iObj1))
// Object { fprot13: {…} }
// AVEC FIREFOX
Le Prototype en Java/Ecma-Script
16 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
// AVEC YANDEX
Exécution :
Le Prototype en Java/Ecma-Script
17 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
Nous avons vu dans le code ci-dessus comment définir une nouvelle
propriété d’un objet, selon le modèle suivant :
<script type="text/javascript"> `use strict`;
const objet={};
console.dir(Object.getOwnPropertyDescriptors(objet));
Le Prototype en Java/Ecma-Script
18 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
const v="30 Nov 2018"
Object.defineProperty(objet, 'newProp',
{ // Property Descriptor
value: v,
configurable: true,
enumerable: true,
writable: true
}
);
console.dir(objet);
console.dir(Object.getOwnPropertyDescriptors(objet));
</script>
Voici comment ajouter plusieurs nouvelles propriétés en une seule opération :
<script type="text/javascript"> `use strict`;
let objet={};
console.dir(Object.getOwnPropertyDescriptors(objet));
Le Prototype en Java/Ecma-Script
19 / 38 jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
const v="30 Nov 2018"
objet = Object.defineProperties({}, // Dummy Object.
{ // Property Descriptors
'newProp1': // Une des Property Descriptors
{
value: v,
configurable: true,
enumerable: true,
writable: true
},
'newProp2': // Une autre Property Descriptor
{
value: "22h10h",
configurable: true,
enumerable: true,
writable: false // ***************
}
}
);
console.dir(objet);
console.dir(Object.getOwnPropertyDescriptors(objet));
objet.newProp1 = "New Value";
objet.newProp2 = "Non writable"; // Aucune alerte !
console.dir(objet);
console.dir(Object.getOwnPropertyDescriptors(objet));
</script>
Le Prototype en Java/Ecma-Script
20 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
La chaîne du prototype :
JavaScript est un langage basé sur le prototype (prototype-based language). On préfère même dire que c’est un système basé sur la délégation (delegation-based system), c’est-à-dire que chaque objet a une
chaîne de prototype (prototype chain) :
Quand vous tentez d’accéder à une propriété ou méthode d’un objet (en
cours de création ou d’instanciation ou une instance d’objet), il se passe
ceci : 1. Si cette propriété existe comme telle dans l’objet en soi, elle est
récupérée ; 2. Si cette propriété n’existe pas en soi dans cet objet, elle est
cherchée dans le prototype de l’object ; le prototype est un objet délégué
(delegate object) c’est-à-dire que la recherche de la propriété est déléguée à l’objet « prototype » (prototype object) qui est une propriété de
l’objet manipulé. Si l’objet prototype possède la propriété cherchée,
Le Prototype en Java/Ecma-Script
21 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
celle-ci est récupéré, sinon elle est éventuellement cherchée dans le prototype du prototype, 3... Ainsi de suite la recherche se poursuit (chaîne
du prototype) jusqu’à l’objet racine souvent le Object (avec « O » majuscule) et éventuellement son prototype (prototype de l’objet racine
=root prototype) souvent le prototype de Object « Object.prototype ».
<script type="text/javascript"> "use strict";
// Constructeur AVEC SA PROPRE toString().
function dObj1() {
this.toString=_=> "... dans dObj1.toString()";
return("Un Objet retourne sa propre copie.")
}
console.log(dObj1);
// function dObj1()
console.log(""+dObj1);
/* function dObj1() {
this.toString=_=> "... dans dObj1.toString()";
return("Un Objet retourne sa propre copie.")
}
*/
let iObj1=new dObj1();
// iObj1 n'a pas de toString() propre
// => chaîne de prototype vers son constructeur
// dObj1.toString() ou dObj1.prototype.toString()
console.log(iObj1);
// Object { toString: toString() }
console.log(""+iObj1);
// ... dans dObj1.toString()
console.log("*AAAAA* "+dObj1);
/* *AAAAA* function dObj1() {
this.toString=_=> "... dans dObj1.toString()";
return("Un Objet retourne sa propre copie.")
}
*/
console.log("*AAAAA* "+dObj1.__proto__.toString());
// *AAAAA* function () {}
Le Prototype en Java/Ecma-Script
22 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
console.log("*BBBBB* "+iObj1);
// *BBBBB* Object { toString: toString() }
console.log("*DDDDD* "+iObj1.__proto__.toString());
// *DDDDD* [object Object]
// Constructeur SANS toString() PROPRE
function dObj2() {
//
Pas de propriété toString() propre
}
console.log(dObj2);
// function dObj2()
console.log(""+dObj2);
/* function dObj2() {
//
Pas de propriété toString() propre
}
*/
let iObj2=new dObj2();
// iObj2 n'a pas de toString() propre
// ni son constructeur => chaîne de prototype
// vers toString du constructeur du constructeur
// ou du prototype du constructeur du constructeur.
console.log(iObj2);
// bject { }
console.log(""+iObj2);
// [object Object]
console.log("*AAAAA* "+dObj2);
/* *AAAAA* function dObj2() {
//
Pas de propriété toString() propre
}
*/
console.log("*AAAAA* "+dObj2.__proto__.toString());
// *AAAAA* function () {}
console.log("*BBBBB* "+iObj2);
// *BBBBB* [object Object]
console.log("*DDDDD* "+iObj2.__proto__.toString());
Le Prototype en Java/Ecma-Script
23 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
//
JavaScript Tome-V
*DDDDD* [object Object]
// Constructeur SANS toString() PROPRE,
// mais ayant toString() dans son prototype.
function dObj3() {
}
dObj3.prototype.toString=_=> console.log("toString de protot
ype")
// toString de prototype
console.log(dObj3);
// function dObj3()
console.log(""+dObj3);
// function dObj3() {}
let iObj3=new dObj3();
// iObj3 n'a pas de toString() propre
// ni son constructeur => chaîne de prototype
// vers toString du constructeur du constructeur
// ou du prototype du constructeur du constructeur.
console.log(iObj3);
// Object { }
console.log(""+iObj3);
// undefined
console.log("*AAAAA* "+dObj3);
// *AAAAA* function dObj3() {}
console.log("*AAAAA* "+dObj3.__proto__.toString());
// *AAAAA* function () {}
console.log("*BBBBB* "+iObj3);
// *BBBBB* undefined
console.log("*DDDDD* "+iObj3.__proto__.toString());
//
*DDDDD* undefined
// APPEL DE CONSTRUCTEUR ET OBJET COMME FONCTIONS ORDINAIRES
// TypeError: this is undefined test.html:4:8
// dObj1 file:///K:/DADET/PROGS/test.html:4:8
// <anonyme> file:///K:/DADET/PROGS/test.html:121:10
Le Prototype en Java/Ecma-Script
24 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
/////////
dObj1();
//
// TypeError: iObj1 is not a function test.html:124:10
/////////
iObj1();
// CHRONOLOGIE DES EXÉCUTIONS AVEC MAXTHON:
/*
2018-02-25 15:33:08.364 test.html:8
function dObj1() {
this.toString=_=> "... dans dObj1.toString()";
return("Un Objet retourne sa propre copie.")
}
2018-02-25 15:33:08.386 test.html:10
function dObj1() {
this.toString=_=> "... dans dObj1.toString()";
return("Un Objet retourne sa propre copie.")
}
2018-02-25 15:33:08.386 test.html:21
dObj1 {}
2018-02-25 15:33:08.388 test.html:23
... dans dObj1.toString()
2018-02-25 15:33:08.388 test.html:26
*AAAAA* function dObj1() {
this.toString=_=> "... dans dObj1.toString()";
return("Un Objet retourne sa propre copie.")
}
2018-02-25 15:33:08.388 test.html:33
*AAAAA* function () {}
2018-02-25 15:33:08.388 test.html:36
*BBBBB* ... dans dObj1.toString()
2018-02-25 15:33:08.389 test.html:39
*DDDDD* [object Object]
2018-02-25 15:33:08.389 test.html:48
dObj2() {
//
Pas de propriété toString() propre
}
2018-02-25 15:33:08.389 test.html:50
function dObj2() {
//
Pas de propriété toString() propre
}
2018-02-25 15:33:08.389 test.html:61
dObj2 {}
2018-02-25 15:33:08.389 test.html:63
Le Prototype en Java/Ecma-Script
25 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
[object Object]
2018-02-25 15:33:08.389 test.html:66
*AAAAA* function dObj2() {
//
Pas de propriété toString() propre
}
2018-02-25 15:33:08.390 test.html:72
*AAAAA* function () {}
2018-02-25 15:33:08.390 test.html:75
*BBBBB* [object Object]
2018-02-25 15:33:08.390 test.html:78
*DDDDD* [object Object]
2018-02-25 15:33:08.390 test.html:89
dObj3() {}
2018-02-25 15:33:08.390 test.html:91
function dObj3() {}
2018-02-25 15:33:08.390 test.html:99
dObj3 {}
2018-02-25 15:33:08.390 test.html:86
toString de prototype
2018-02-25 15:33:08.390 test.html:101
undefined
2018-02-25 15:33:08.390 test.html:104
*AAAAA* function dObj3() {}
2018-02-25 15:33:08.390 test.html:107
*AAAAA* function () {}
2018-02-25 15:33:08.391 test.html:86
toString de prototype
2018-02-25 15:33:08.391 test.html:110
*BBBBB* undefined
2018-02-25 15:33:08.391 test.html:86
toString de prototype
2018-02-25 15:33:08.391 test.html:113
*DDDDD* undefined
*/
</script>
CHRONOLOGIE DES EXÉCUTIONS AVCE FIREFOX :
function dObj1()
test.html:8:4
function dObj1() {
this.toString=_=> "... dans dObj1.toString()";
Le Prototype en Java/Ecma-Script
26 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
return("Un Objet retourne sa propre copie.")
}
test.html:10:4
Object { toString: toString() }
test.html:21:4
... dans dObj1.toString()
test.html:23:4
*AAAAA* function dObj1() {
this.toString=_=> "... dans dObj1.toString()";
return("Un Objet retourne sa propre copie.")
}
test.html:26:4
*AAAAA* function () {
}
test.html:33:4
*BBBBB* ... dans dObj1.toString()
test.html:36:4
*DDDDD* [object Object]
test.html:39:4
function dObj2()
test.html:48:4
function dObj2() {
//
Pas de propriété toString() propre
}
test.html:50:4
Object { }
test.html:61:4
[object Object]
test.html:63:4
*AAAAA* function dObj2() {
//
Pas de propriété toString() propre
}
test.html:66:4
*AAAAA* function () {
}
test.html:72:4
*BBBBB* [object Object]
test.html:75:4
*DDDDD* [object Object]
test.html:78:4
function dObj3()
test.html:89:4
function dObj3() {
}
test.html:91:4
Object { }
test.html:99:4
toString de prototype
test.html:86:33
undefined
test.html:101:4
*AAAAA* function dObj3() {
}
test.html:104:4
*AAAAA* function () {
}
test.html:107:4
toString de prototype
test.html:86:33
*BBBBB* undefined
test.html:110:4
toString de prototype
test.html:86:33
*DDDDD* undefined
test.html:113:4
Le prototype est comme une banque des propriétés par défaut de l’objet
et surtout ses instances, pouvant donc être partagées avec les descendants (instances) de cet objet. Mais en plus des propriétés du prototype,
Le Prototype en Java/Ecma-Script
27 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
l’objet peut avoir ses propriétés propres non stockées dans le prototype
(propriétés non membres de son prototype).
En d’autres termes :
Toute propriété du prototype d’un objet appartient aussi à cet objet, mais
certaines propriétés de l’objet ne sont pas nécessairement propriétés de son
prototype (et donc sont non héritables), une instance d’objet pouvant aussi
avoir des « ownProperties ».
Implications de la chaîne de prototype :
Considérons cet objet parent (constructeur) :
<script type="text/javascript"> "use strict";
let oParent = function(p){ }
// objet vide avec prototype implicite, vide.
</script>
Créons deux instances de cet objet parent oParent, comme suit :
<script type="text/javascript"> "use strict";
let iObjet1 = new oParent();
<script type="text/javascript"> "use strict";
function oParent(){ }
let iObjet1 = new oParent();
let iObjet2 = new oParent();
// Ajoutons une propriété
// dans le prototype du constructeur
oParent.prototype.distance={
par_avion:"1000 km",
par_route:"2500km"
}
console.log(iObjet1.distance);
Le Prototype en Java/Ecma-Script
28 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
console.log(iObjet2.distance);
</script>
Les deux instances iObjet1 et iObjet2 héritent automatiquement de cette
nouvelle propriété définie dans le prototype de l’objet parent.
Par exemple, les deux instances afficheront distance.par_avion = 1000
km :
Exécution du programme :
Object { par_avion: "1000 km", par_route: "2500km" }
test.html:15:4
Object { par_avion: "1000 km", par_route: "2500km" }
test.html:16:4
Exécution à la console du browser :
console.log(iObjet1.distance.par_avion);
console.log(iObjet2.distance.par_avion);
console.log(iObjet1.distance.par_route);
console.log(iObjet2.distance.par_route);
En tapant ceci à la console du browser :
iObjet1.distance.par_avion
iObjet2.distance.par_avion
iObjet2.distance.par_route
iObjet1.distance.par_route
"1000 km"
"1000 km"
"2500km"
"2500km"
console.log(iObjet1.distance.par_avion)
debugger eval code:1:1
undefined
1000 km
console.log(iObjet2.distance.par_avion)
1000 km
Le Prototype en Java/Ecma-Script
29 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
debugger eval code:1:1
undefined
console.log(iObjet1.distance.par_route)
debugger eval code:1:1
undefined
2500km
console.log(iObjet2.distance.par_route)
debugger eval code:1:1
undefined
2500km
Si nous redéfinissons la distance pour l’instance par exemple seulement
celle de iObjet2, comme ceci :
iObjet2.distance.par_route = "3500 km";
Comme iObjet2 n’a pas la propriété distance parmi ses OwnProperties,
l’ordinateur considérera que c’est la propriété distance du prototype du
parent (constructeur) que l’on a voulu modifier, et modifiera donc ce
prototype du constructeur, et l’effet se manifestera à toutes les instances
du constructeur.
Ainsi donc, en tentant d’afficher la distance par_route de l’instance
iObjet1, c’est la distance redéfinie pour l’objet iObjet2 (3500 km) qui
sera affichée.
Si on avait défini la distance comme une propriété-objet comme ceci,
elle serait automatiquement considérée comme propriété propre (faisant
partie seulement) de iObjet2 :
iObjet2.distance={
par_avion : "1750 km",
par_route : "3500 km"
}
console.log(iObjet1.distance.par_avion); // 1000 km
console.log(iObjet2.distance.par_avion); // 1750 km
Le Prototype en Java/Ecma-Script
30 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
console.log(iObjet1.distance.par_route); // 3500 km
console.log(iObjet2.distance.par_route); // 3500 km
Le tout donne :
<script type="text/javascript"> "use strict";
let oParent = function(p){
}
// objet vide avec prototype implicite, vide.
let iObjet1 = new oParent();
let iObjet2 = new oParent();
oParent.prototype.distance={
par_avion:"1000 km",
par_route:"2500km"
}
console.log(iObjet1.distance.par_avion);
console.log(iObjet2.distance.par_avion);
console.log(iObjet1.distance.par_route);
console.log(iObjet2.distance.par_route);
//
//
//
//
1000 km
1000 km
2500km
2500km
//
//
//
//
1000
1000
3500
3500
km
km
km
km
//
//
//
//
1000
1000
3500
3500
km
km
km
km
iObjet2.distance.par_route = "3500 km";
console.log(iObjet1.distance.par_avion);
console.log(iObjet2.distance.par_avion);
console.log(iObjet1.distance.par_route);
console.log(iObjet2.distance.par_route);
iObjet2.distance={
par_avion : "1750 km",
par_route : "3500 km"
}
console.log(iObjet1.distance.par_avion);
console.log(iObjet2.distance.par_avion);
console.log(iObjet1.distance.par_route);
console.log(iObjet2.distance.par_route);
</script>
Le Prototype en Java/Ecma-Script
31 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
Dans la dissection ci-dessous nous voyons que le prototype dépend du
fait que notre constructeur ait des paramètres formels ou pas, et s’il
comporte des « this » ou pas, peu importe s’il est instancié. Un constructeur sans « this » est une fonction ordinaire, mais bien entendu une fonction est bel et bien un objet).
I. Sans paramètres formels avec ou sans « this » et même avec un
corps vide :
<script type="text/javascript">
'use strict';
// Fonction ordinaire
function dObj(){
var fdObj = function(){
return("Insiding dObj.fdObj")
}
}
console.log(dObj)
</script>
Nous voyons dans la console de FireFox que le prototype implicite (par
défaut) de notre fonction est l’objet objet, et celui de son parent est [aussi] une fonction.
function dObj()
dObj()
length: 0
name: "dObj"
prototype: Object { … }
__proto__: function ()
En déroulant ses éléments dans la console, nous obtenons ceci :
Dans le prototype par défaut de notre fonction dObj() celle-ci est bel et
bien un/le constructeur.
dObj()
length: 0
Le Prototype en Java/Ecma-Script
32 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
name: "dObj"
prototype: {…}
constructor: function dObj()
__proto__: Object { … }
__proto__: ()
apply: function apply()
arguments: null
bind: function bind()
call: function call()
caller: null
constructor: function Function()
isGenerator: function isGenerator()
length: 0
name: ""
toSource: function toSource()
toString: function toString()
Symbol(Symbol.hasInstance): undefined
__proto__: Object { … }
Son constructeur est un objet [__proto__ du prototype de dObj :
« dObj() - prototype: (...) - __proto__ »] est Object.
En déroulant ce __proto__ nous voyons que le constructeur de ce prototype est la fonction Object() que nous savons être un objet (l’objet parent de tous les autres objets). Nous voyons qu’il n’est pas affiché le
__proto__ (parent) de Object : l’objet objet n’a pas de parent, il n’est
fils de rien..
prototype: Object { … }
prototype: {…}
constructor: function dObj()
__proto__: {…}
__defineGetter__: function __defineGetter__()
__defineSetter__: function __defineSetter__()
__lookupGetter__: function __lookupGetter__()
__lookupSetter__: function __lookupSetter__()
constructor: function Object()
hasOwnProperty: function hasOwnProperty()
isPrototypeOf: function isPrototypeOf()
propertyIsEnumerable: function propertyIsEnumerable()
Le Prototype en Java/Ecma-Script
33 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
toLocaleString: function toLocaleString()
toSource: function toSource()
toString: function toString()
unwatch: function unwatch()
valueOf: function valueOf()
watch: function watch()
Nous pouvons aussi y voir les autres propriétés du prototype de cet Object parent du prototype de dObj :
function __defineGetter__(), function __defineSetter__(),
function __lookupGetter__(), function __lookupSetter__(),
constructor: function Object()
function hasOwnProperty(), function isPrototypeOf(), function propertyIsEnumerable(), function toLocaleString(),
function toSource(), function toString(), function unwatch(), function valueOf(), function watch()
Nous avons vu là, le prototype du constructeur du prototype implicite de
notre fonction dObj() (qui est en fait aussi un objet). Voyons maintenant
le prototype du constructeur de notre fonction dObj() : « dObj() __proto__ » :
Nous y voyons que le constructeur de notre fonction est une fonction
(__proto__: function ()).
Déroulons ce prototype du parent :
Nous voyons que le constructeur de ce parent est une fonction, la fonction Function (avec « F » majuscule, qui est aussi bien entendu un objet,
le constructeur [pas « parent »] de l’objet Object et de la fonction Functiont). Ce constructeur parent a un __proto__ (comprenez « prototype du
parent » ou tout simplement « le parent »), comme on peut le voir cidessous, qui est l’objet Object, parent de tous les objets y compris les
fonctions (comme on le constate ici).
Le Prototype en Java/Ecma-Script
34 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
Mais attention, ne confondez pas l’objet générique « Object » et l’objet
global « window » qu’on peut nommer ou pas et qui renferme entre
autres les propriétés suivantes :
Infinity , NaN , undefined , eval() , isFinite() , isNaN() , parseFloat() ,
parseInt() , decodeURI() , decodeURIComponent() , encodeURI() , encodeURIComponent() , Math , JSON , Reflect , Object() , Function() ,
Boolean() , Number() , String() , Symbol() , Array() , Float32Array() ,
Float64Array() , Int8Array() , Int16Array() , Int32Array() ,
Uint8Array() , Uint8ClampedArray() , Uint16Array() , Uint32Array() ,
ArrayBuffer() , DataView() , Date() , RegExp() , Set() , WeakSet() ,
Map() , WeakMap() , Proxy() , Promise() , Error() , SyntaxError() ,
RangeError() , TypeError() , ReferenceError() , URIError() , EvalError().
Il n’est pas nécessaire de retenir par coeur cette liste partielle (mais il
faut connaître leur existence), vous pouvez obtenir la liste exhaustive à
la console du navigateur en tapant
« Object.getOwnPropertyNames(window) ».
Baidu en liste 591, Maxthon 753, UC Browser 771, Torch 781, FireFox
794, Yandex 807, Google Chrome 808, Vivaldi 809, Opera 813, Brave
814, UR Brower 831,...
Toutes les propriétés de l’objet global window sont disponibles
(=accesibles) directement de partout sans préfixer du nom d’objet
« window ». Dans l’espace global (càd en dehors de toute fonction),
« this » est l’alias de « window ».
__proto__: ()
apply: function apply()
arguments: null
bind: function bind()
call: function call()
caller: null
constructor: function Function()
Le Prototype en Java/Ecma-Script
35 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
isGenerator: function isGenerator()
length: 0
name: ""
toSource: function toSource()
toString: function toString()
Symbol(Symbol.hasInstance): undefined
__proto__: Object { … }
En déroulant le constructeur « function Function » nous pouvons voir
ses propriétés dont encore un __proto__ qui est une fonction :
constructor: Function()
length: 1
name: "Function"
__proto__: function ()
En déroulant ce __proto__: function() (= prototype du constructeur et
qui est une fonction) nous obtenons :
__proto__: ()
apply: function apply()
arguments: null
bind: function bind()
call: function call()
caller: null
constructor: function Function()
isGenerator: function isGenerator()
length: 0
name: ""
toSource: function toSource()
toString: function toString()
Symbol(Symbol.hasInstance): undefined
__proto__: Object { … }
Les propriétés de cet objet Function sont donc :
Méthodes :
function apply(), function bind(), function call(), function Function(), function isGenerator(), function toSource(), function toString(),
Le Prototype en Java/Ecma-Script
36 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
Propriétés :
arguments: null, caller: null, length: 0, name: "", Symbol(Symbol.hasInstance): undefined
En déroulant ce __proto __ : Object {...} nous tombons de nouveau sur
l’objet Object qui n’a pas de __proto__ donc pas de parent (pas de
constructeur).
II. Avec des paramètres formels avec ou sans « this » :
Notre fonction dObj() n’a aucun prototype même pas le prototype par
défaut, donc aucune propriété initiale. Mais il a un __proto__ qui est le
même constructeur que la forme sans paramètres.
Le Prototype en Java/Ecma-Script
37 / 38
jeudi, 4. avril 2019
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-V
Kinshasa, le 4 avril 2019 (10:47 ).
Mots-clés :
Void, chaîne du prototype, JavaScript, prototype, prototype-based
language, délégation, delegation-based system, prototype chain,
objet délégué, delegate object, objet prototype, prototype object,
objet racine, root prototype, Object.prototype
DIASOLUKA Nz. Luyalu
Docteur en Médecine, Chirurgie & Accouchements (1977),
CNOM : 0866 - Spécialiste en ophtalmologie (1980)
Études humanités : Scientifique - Mathématiques & Physique.
Informaticien-amateur, Programmeur et WebMaster.
Chercheur indépendant, autonome et autofinancé, bénévole, sans
aucun conflit d’intérêt ou liens d'intérêts ou contrainte
promotionnelle avec qui qu’il soit ou quelqu’organisme ou
institution / organisation que ce soit, étatique, paraétatique ou privé,
industriel ou commercial en relation avec le sujet présenté.
+243 - 851278216 - 899508675 - 991239212 - 902263541 - 813572818
[email protected]
Le Prototype en Java/Ecma-Script
38 / 38
jeudi, 4. avril 2019