Vous êtes sur la page 1sur 38

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


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 proto-
type, et automatiquement ces nouvelles propriétés seront partagées avec
toutes les instances de cet objet. Bien entendu on peut aussi ajouter di-
rectement 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éfini-
tion 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 pro-


totype pour un objet :

<script type="text/javascript"> "use strict";


let t=" Object.setPrototypeOf()",
l=t.length+5,m=l+5;
console.log("".padStart(m,"*"));
console.log(t.padStart(l,"*").padEnd(m,"*"));
console.log("*".repeat(m));
J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-V
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: ƒ}
// __proto__: ƒ ()
// [[FunctionLocation]]: test.html:8
// [[Scopes]]: Scopes[2]
// __proto__: Object

Le Prototype en Java/Ecma-Script 2 / 38 mardi, 22. janvier 2019


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-V

console.log(iObj1.prototype); // undefined
console.log(iObj_1.prototype); // 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 :

********************************** test.html:4:3

Le Prototype en Java/Ecma-Script 3 / 38 mardi, 22. janvier 2019


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-V

Avec Yandex:

Le Prototype en Java/Ecma-Script 4 / 38 mardi, 22. janvier 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;
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);
Le Prototype en Java/Ecma-Script 5 / 38 mardi, 22. janvier 2019
J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-V
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(), … }
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--;
Le Prototype en Java/Ecma-Script 6 / 38 mardi, 22. janvier 2019
J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-V
}
}
return this;
}
con-
sole.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(){}

// 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()

Le Prototype en Java/Ecma-Script 7 / 38 mardi, 22. janvier 2019


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-V
// 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


// 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");

Le Prototype en Java/Ecma-Script 8 / 38 mardi, 22. janvier 2019


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-V

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:
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 */

Le Prototype en Java/Ecma-Script 9 / 38 mardi, 22. janvier 2019


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-V
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

/* 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 !

Le Prototype en Java/Ecma-Script 10 / 38 mardi, 22. janvier 2019


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-V
// 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
////
//== 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.

Le Prototype en Java/Ecma-Script 11 / 38 mardi, 22. janvier 2019


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-V
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 */
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

Le Prototype en Java/Ecma-Script 12 / 38 mardi, 22. janvier 2019


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-V

// 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");
//-- FIREFOX: TypeError:
//-- iObj.prototype is undefined
////
//== YANDEX: Uncaught TypeError:
//== Cannot set property 'fprot43' of undefined
//== at test.html:238

console.log(iObj4.prototype); // undefined
console.log(dObj4.prototype); // 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>

Le Prototype en Java/Ecma-Script 13 / 38 mardi, 22. janvier 2019


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-V

console.log(Object.getOwnPropertyDescriptors(dObj4))
// Object { fprot42: {…}, length: {…}, name: {…} }

// fprot42: Object {} AVEC FIREFOX

// fprot42: Object {} AVEC YANDEX

// name: Object {} AVEC FIREFOX

Le Prototype en Java/Ecma-Script 14 / 38 mardi, 22. janvier 2019


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-V

// name: Object {} AVEC YANDEX

// length: Object {} AVEC FIREFOX

// length: Object {} AVEC YANDEX

// prototype: Object {} AVEC FIREFOX

Le Prototype en Java/Ecma-Script 15 / 38 mardi, 22. janvier 2019


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-V

// prototype: Object {} AVEC YANDEX

console.log(Object.getOwnPropertyDescriptors(iObj1))
// Object { fprot13: {…} }

// AVEC FIREFOX

Le Prototype en Java/Ecma-Script 16 / 38 mardi, 22. janvier 2019


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-V

// AVEC YANDEX

Exécution :

Le Prototype en Java/Ecma-Script 17 / 38 mardi, 22. janvier 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 mardi, 22. janvier 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éra-


tion :

<script type="text/javascript"> `use strict`;


let objet={};
console.dir(Object.getOwnPropertyDescriptors(objet));
Le Prototype en Java/Ecma-Script 19 / 38 mardi, 22. janvier 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 mardi, 22. janvier 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 lan-


guage). On préfère même dire que c’est un système basé sur la déléga-
tion (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 mardi, 22. janvier 2019


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-V
celle-ci est récupéré, sinon elle est éventuellement cherchée dans le pro-
totype du prototype, 3... Ainsi de suite la recherche se poursuit (chaîne
du prototype) jusqu’à l’objet racine souvent le Object (avec « O » ma-
juscule) 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 mardi, 22. janvier 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 mardi, 22. janvier 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 mardi, 22. janvier 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 mardi, 22. janvier 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 mardi, 22. janvier 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 descen-
dants (instances) de cet objet. Mais en plus des propriétés du prototype,
Le Prototype en Java/Ecma-Script 27 / 38 mardi, 22. janvier 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 mardi, 22. janvier 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 "1000 km"


iObjet2.distance.par_avion "1000 km"
iObjet2.distance.par_route "2500km"
iObjet1.distance.par_route "2500km"

console.log(iObjet1.distance.par_avion) 1000 km
debugger eval code:1:1
undefined

console.log(iObjet2.distance.par_avion) 1000 km

Le Prototype en Java/Ecma-Script 29 / 38 mardi, 22. janvier 2019


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-V
debugger eval code:1:1
undefined

console.log(iObjet1.distance.par_route) 2500km
debugger eval code:1:1
undefined

console.log(iObjet2.distance.par_route) 2500km
debugger eval code:1:1
undefined

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 mardi, 22. janvier 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); // 1000 km
console.log(iObjet2.distance.par_avion); // 1000 km
console.log(iObjet1.distance.par_route); // 2500km
console.log(iObjet2.distance.par_route); // 2500km

iObjet2.distance.par_route = "3500 km";

console.log(iObjet1.distance.par_avion); // 1000 km
console.log(iObjet2.distance.par_avion); // 1000 km
console.log(iObjet1.distance.par_route); // 3500 km
console.log(iObjet2.distance.par_route); // 3500 km

iObjet2.distance={
par_avion : "1750 km",
par_route : "3500 km"
}

console.log(iObjet1.distance.par_avion); // 1000 km
console.log(iObjet2.distance.par_avion); // 1000 km
console.log(iObjet1.distance.par_route); // 3500 km
console.log(iObjet2.distance.par_route); // 3500 km

</script>

Le Prototype en Java/Ecma-Script 31 / 38 mardi, 22. janvier 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 construc-
teur sans « this » est une fonction ordinaire, mais bien entendu une fonc-
tion 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 [aus-
si] 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 mardi, 22. janvier 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 proto-


type est la fonction Object() que nous savons être un objet (l’objet pa-
rent 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 mardi, 22. janvier 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 Ob-
ject parent du prototype de dObj :

function __defineGetter__(), function __defineSetter__(),


function __lookupGetter__(), function __lookupSetter__(),

constructor: function Object()

function hasOwnProperty(), function isPrototypeOf(), func-


tion propertyIsEnumerable(), function toLocaleString(),
function toSource(), function toString(), function un-
watch(), 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 fonc-


tion Function (avec « F » majuscule, qui est aussi bien entendu un objet,
le constructeur [pas « parent »] de l’objet Object et de la fonction Func-
tiont). Ce constructeur parent a un __proto__ (comprenez « prototype du
parent » ou tout simplement « le parent »), comme on peut le voir ci-
dessous, 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 mardi, 22. janvier 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() , en-
codeURIComponent() , 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() , EvalEr-
ror().

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 mardi, 22. janvier 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(), func-
tion Function(), function isGenerator(), function to-
Source(), function toString(),

Le Prototype en Java/Ecma-Script 36 / 38 mardi, 22. janvier 2019


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-V
Propriétés :
arguments: null, caller: null, length: 0, name: "", Sym-
bol(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 mardi, 22. janvier 2019


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-V

Kinshasa, le 22 janvier 2019 (8:54 ).

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

diasfb@mail2world.com

Le Prototype en Java/Ecma-Script 38 / 38 mardi, 22. janvier 2019

Vous aimerez peut-être aussi