Je voudrais savoir s'il est possible de passer par reference un argument en javascript . si oui comment procède t-on? Merci
Version imprimable
Je voudrais savoir s'il est possible de passer par reference un argument en javascript . si oui comment procède t-on? Merci
Si je ne me trompe pas, les arguments en javascript sont tous passés en référence, hormis les types primitifs.
A confirmer.
Vrai. Les types primitifs en JS sont les nombres et les booléens. Tout le reste est objet donc passé par référence, ce qui inclut les chaînes, les tableaux, les fonctions, etc.
Exemple avec un objet littéral :
Certains sont tentés de déclarer toutes leurs variables avec new, y compris celles de type primitif, par exemple new Number(42). C'est une mauvaise idée, car en faisant ça on crée en fait un objet et les avantages du type primitif sont perdus.Code:
1
2
3
4
5
6
7
8
9 var obj = {}; function ajouterProp(o) { o.prop = "bonjour"; } ajouterProp(obj); // obj est automatiquement passé par référence console.log(o.prop); // affiche "bonjour" dans la console
Les arguments d'une fonction en Javascript sont tous sans exception, c'est à dire quel que soit leur type objet ou pas, passés par valeur et non par référence.
La spécificité d'un passage par référence est que dans l'appelant, l'argument passé peut revenir modifié. On ne parle pas de son contenu, mais de l'argument lui même.
Quels que soient les types et valeurs pour a et b.Code:
1
2
3
4
5
6
7
8
9
10
11
12 // Soit une fonction qui échange ses arguments : function swap ( a, b ) { var t = a; a = b; b = t; } var a = 1, b = "deux"; swap(a,b); // Si a et b étaient passés par référence, on aurait // a == "deux" et b == 1 // mais ici, on aura toujours // a == 1 et b == "deux"
Je rejoins kaari & Watilin sur ce point pour ma part tout ce qui est objet sera passé par référence, tout ce qui est primitive sera par valeur.
Ton exemple lysandro, utilise deux primitives. Un Number & un String
Exemple avec un Objet :
http://img4.hostingpics.net/pics/172944jsref.jpg
C'est bien l'adresse de l'objet qui est passée.
je ne sais pas quel est le langage de préilection de lysandro
Mais je pense qu'il y a confusion sur le terme référence.
il existe 3 façon de passer une variable à une fonction.
Par valeur
Par référence
Par pointeur
Le passage par valeur est facile à comprendre.
La valeur est donnée à la fonction et celle-ci ne connait pas la variable. elle ne peut donc pas la modifier.
Le passage par référence conciste à donner une référence à la variable en parrametre à la fonction.
La fonction a donc connaissance de la variable et peut en modifier la valeur. mais elle ne peut pas modifier la variable elle même.
par exemple si je passe un objet User dont le nom est toto je peut modifier le non de User mais cela restera User.
Le passage par pointeur conciste à donner une référence sur l'adresse de la variable.
la fonction peut donc accéder à la valeur.
elle a aussi connaissance de la variable et peut modifier sa valeur
mais comme elle a une référence à l'adresse elle peut aussi modifier cette référence.
la chose se résume ainsi
soit deux varaible référençant le même objetAppel par valeur f(a); l'objet référencé par a et par b n'a pas changéCode:
1
2
3
4
5 +--------+ a ->| | | x:15 | b ->| | +--------+
Appel par référence f(a); l'objet référencé par a et par b a pas changé mais a et b référence toujour cet objetCode:
1
2
3
4
5 +--------+ a ->| | | x:15 | b ->| | +--------+
Appel par pointf(a); l'objet référencé par a n'est plus le même que celui référencé par b.Code:
1
2
3
4
5 +--------+ a ->| | | x:32 | b ->| | +--------+
En Javascript seuls les passage par valeur pour les type primitifs et par référence pour tout le reste existe.Code:
1
2
3
4
5
6
7 +--------+ a ->| x:32 | +--------+ +--------+ b ->| x:15 | +--------+
A+JYT
Les chaînes de caractères sont des primitives aussi !
http://msdn.microsoft.com/en-us/libr...(v=vs.94).aspx
https://developer.mozilla.org/fr/doc...e_donn%C3%A9es
Si on prend comme définition de primitive tout ce qui n'est pas objet, on a bien "string" instanceof Object === false.
Je pense que sekaijin a vu juste. Je pense que Kouamé josué veut savoir si on peut passer des arguments par référence à une fonction. Exemple en PHP :
Code:
1
2
3
4
5
6
7
8 $maVariable = 'coucou'; function changeCoucou(&$a) { $a = 'toto'; } changeCoucou($maVariable); // $maVariable vaut maintenant 'toto'
En JavaScript, il n'y a pas d'équivalent de l'opérateur & devant les paramètres d'une fonction.
J'ai ici pris 4, mais ça vaut pour toutes les primitives (voir ci-dessous la définition).Code:
1
2
3
4
5
6
7
8 function changeX(x) { x = 5; // x ici est propre au contexte de la fonction changeX. C'est une variable locale à la fonction, accessible que à l'intérieur de cette fonction. } var x = 4; alert(x); // x vaut 4 changeX(x); alert(x); // x vaut toujours 4
Par contre, si tu passes un objet {} ou un array [] :
Code:
1
2
3
4
5
6
7
8 function changeX(x) { x.push('toto'); // on insére 'toto' à la suite du tableau } var x = ['tata']; alert(x); // x vaut ['tata'] changeX(x); alert(x); // x vaut ['tata', 'toto']
Code:
1
2
3
4
5
6
7
8
9
10 function changeX(x) { x.propriete2 = 'toto'; // on ajoute la propriété 'propriete2' ayant pour valeur 'toto' à l'objet } var x = { propriete1: 'tata' }; alert(x); // x vaut {propriete1: 'tata'} changeX(x); alert(x); // x vaut {propriete1: 'tata', propriete2: 'toto'}
Y'a un peu plus de types primitifs en réalité (selon la spéc) :Citation:
Vrai. Les types primitifs en JS sont les nombres et les booléens.
Undefined (undefined), Null (null), Boolean (true ou false), Number (42, 3.14, 1e6, NaN, Infinity, -Infinity ... ils suivent la norme IEEE 754), ou String ("coucou" ou 'coucou')
Merci Sylvain et Kaamo de me corriger, effectivement je me suis bien planté. Et je peux plus éditer mon message :(
Du coup je rajoute que si on manipule des chaînes longues, il faut garder à l'esprit qu'elles sont copiées lorsqu'on les passe à une fonction. Ça peut poser des problèmes de mémoire.
Kaamo avec sa fonction 'changeCoucou()' donne un excellent exemple de passage par référence.
Dans son exemple, on voit bien que c'est '$maVariable' qui est modifiée. C'est impossible à faire en Javascript. Ca ne dépend pas du tout du type de '$maVariable' (enfin je l'espère, je ne connais pas PHP).Code:
1
2
3
4
5
6
7
8 $maVariable = 'coucou'; function changeCoucou(&$a) { $a = 'toto'; } changeCoucou($maVariable); // $maVariable vaut maintenant 'toto'
Le passage par pointeur n'existe pas. Un pointeur c'est un type de variable, ni plus ni moins.
La confusion vient de ce qu'on peut passer par valeur des types modifiables, par exemple un tableau.
Dans le cas de l'appel 'f(b)', on peut modifier le contenu du tableau, en ajoutant ou retirant des éléments. Mais impossible de le mettre à 'null' par exemple.Code:
1
2
3
4
5
6
7
8
9
10
11 function f ( x ) { // code utilisant x } var a = 1; var b = [1]; // à l'appel f(a) // f reçoit 1 <=> f(1) // à l'appel f(b) // f reçoit [1] <=> f([1])
C'est bien la valeur de 'b' qui est passée et non la variable 'b' elle-même.
Par contre, si on pouvait écrire comme en PHP
C'est un passage par référence. On peut modifier la variable 'b' (ou 'a'), pas seulement son contenu. C'est l'exemple de Kaamo.Code:
1
2
3
4
5
6
7
8
9
10
11 function f ( &x ) { // code utilisant x } var a = 1; var b = [1]; // à l'appel f(a) // f reçoit l'adresse mémoire de la variable a <=> f([abcd]) où [abcd] est l'adresse de a qui contient 1 // à l'appel f(b) // f reçoit l'adresse mémoire de la variable b <=> f([wxyz]) où [wxyz] est l'adresse de b qui contient le tableau [1]
On peut remarquer au passage que rien ne distingue les deux formes d'appels, par valeur ou par référence (aussi appelé par variable).
En ce qui concerne le passage de pointeurs, on aurait
C'est toujours un passage par valeur. Dans ce cas trés particulier, on pourrait modifier 'a' qui n'est même pas passé en argument mais toujours pas 'b'.Code:
1
2
3
4
5
6
7
8
9
10
11 function f ( x ) { // passage par valeur // code utilisant x } var a = 1; var *b = &a; // b est un pointeur qui contient l'adresse de a et *b == 1 // à l'appel f(a) // f reçoit 1 <=> f(1) // à l'appel f(b) // f reçoit [1] <=> f([wxyz]) où [wxyz] est l'adresse de b qui contient l'adresse de a:[abcd]
En espérant avoir éclairci ce que je voulais dire
encore une fois les variable sont passé par référence.
en fonction de leur type.
comment fonction un langage interprété
lorsque tu définie une variable tu ajoute une nouvelle entrée dans la table des symboles connu (une espèce de tableau associatif)
cette entrée contien deux chose un nom et une adresse (null est une adress comme une autre.)
à cette adresse ce trouve un contenu (objet, tableau, caractère, nombre, etc.)
Appeller une fonction avec un paramètre consiste à mettre le dit paramètre sur la pile d'éxécution
créer un contexte d'éxécution
puis à exécuter le corps de la fonction.
la premère chose que celle-ci fait c'est prendre le paramètre et définir dans la table des symboles de son contexte
une entrée qui contient le nom du paramètre et le contenu de ce qui est sur la pile d'éxéution.
soit la variable a = 15 (le symbole a est à l'adresse @100 dans la table des symbole et 15 à l'adresse @115)
on place sur la pile 15 (au sommet de la pile adresse @1005)
on créé un contexte
on définit un symbole param (dans le contexte param adresse @256 15 adresse @271)
param = 15
la fonction peut s'éxécuter.
ceci s'appelle un passage par valeur.
soit la variable a = {age:15} (le symbole a est à l'adresse @100 dans la table des symbole et {age:15} à l'adresse @115)
on place sur la pile {age:15} (au sommet de la pile adresse @1005)
on créé un contexte
on définit un symbole param (dans le contexte param adresse @256 {age:15} à l'adresse @115)
param = {age:15}
la fonction peut s'éxécuter.
ceci s'appelle un passage par référence. ce qui est placé sur la pile est @115
soit la variable a = {age:15} (le symbole a est à l'adresse @100 dans la table des symbole et {age:15} à l'adresse @115)
on place sur la pile a (au sommet de la pile adresse @1005)
on créé un contexte
on définit un symbole param (dans le contexte param adresse @256 a à l'adresse @100)
param = {age:15}
la fonction peut s'éxécuter.
ceci s'appelle un passage par pointeur. ce qui est placé sur la pile est @100
le passage par valeur consiste à passer en paramètre la valeur contenue à l'adresse référencé par la variable.
le passage par référence conciste à passer en paramètre l'adresse de l'objet référencé par la variable.
le passage par mointeur consiste à passer en paramètre l'adresse de la varriable pas ce qu'elle référence.
si tu avais fais un passage pas valeur tu auraisdans le cas d'une StringCode:
1
2
3
4
5
6
7
8 @100 @115 +-----+ +--------+ | a |--------->| 15 | +-----+ +--------+ @256 @271 +-----+ +--------+ |param|--------->| 15 | +-----+ +--------+
en javascript on ne mets pas 'Jhon Doe' sur la pile mais on pets bien @115Code:
1
2
3
4 @100 @115 +-----+ +----------+ | a |--------->|'Jhon Doe'| +-----+ +----------+
lorsque tu arrive dans ta fonction tu est dans la situation suivantetu a bien un référence à 'Jhon Doe'Code:
1
2
3
4
5
6
7
8 @100 @115 +-----+ +----------+ | a |---+----->|'Jhon Doe'| +-----+ | +----------+ @256 | +-----+ | |param|---+ +-----+
puis tu faisla variable param ne référence plus 'Jhon Doe' mais 'bill'Code:param = 'bill';
c'est exactement ce que fais javascriptCode:
1
2
3
4
5
6
7
8 @100 @115 +-----+ +----------+ | a |--------->|'Jhon Doe'| +-----+ +----------+ @256 @915 +-----+ +--------+ |param|--------->| 'bill' | +-----+ +--------+
maintenant ce que ferait un passage par pointeurtu n'a plus de référence à l'objet référencé par a mais une référence à a lui-même.Code:
1
2
3
4 @256 @100 @115 +-----+ +-----+ +----------+ |param|--->| a |-------->|'Jhon Doe'| +-----+ +-----+ +----------+
en utilisant la syntaxe adapté qui n'existe pas en javascript tu pourais faire un truc du genrepour obtenirCode:¶m='bill';
Code:
1
2
3
4 @256 @100 @115 +-----+ +-----+ +------+ |param|--->| a |-------->|'bill'| +-----+ +-----+ +------+
en C/C++ tu crée une variable de type pointeur sur string
à l'éxécussion un mot mémoire est loué à l'adresse @100 qui représente ce pointeur
puis tu appelle une fonction qui alloue de la mémoire à l'adresse @248 et affecte cette adresse à ton pointeur.
tu quitte ta fonction et ta variable a pour valeur @248
tu crée une variable de type string
à l'éxécussion un mot mémoire est loué à l'adresse @100 qui représente ce pointeur
tu affecte à cette variable une string allouée à l'adresse @248
tu appelle une fonction en passant la variable par référence qui change le premier caractère en Majuscule.
tu quitte ta fonction. ta variable à le contenu de son premier caractère en majuscule
que c'est il passé dans le premier cas tu as mis @100 sur la pile qui est l'adresse du pointeur tu as bien passé le pointeur
dans le deuxième tu as mis @248 sur la pile qui est bien ce qui est référencé par ta variable.
avec un passage par valeur si ta variable contenait 'jhon doe' tu n'aurais pas mis @248 sur la pile mais 'jhon doe'
le compilateur C et suffisement sioux pour ne pas faire ça.
soit il ne peut y avoir de modif et il met @248 sachant que la fonction en modifira pas l'objet
soit il y a un risque et il copie 'jhon doe' dans une autre zone @1452 par exemple et place @1452 sur la pile.
mais ça c'est juste une optimisation.
lire la théorie de la compilation et de l'interprétation des langages informatique.
A+JYT
Ok, j'ai fait un contresens sur la question posée initalement, désolé.
Mais ça ne change rien :-) Il suffit de faire une recherche dans un moteur avec 'passage par référence'.
Maintenant, le fait que pour certains arguments ce soit l'adresse qui soit passée (sur une pile ou pas d'ailleurs) ne change pas le type du passage des arguments.
Je comprends que vous faites la différence entre passer une adresse ou le contenu, mais ce n'est pas ce qu'usuellement j'appelle un passage par référence ou par valeur.
Puisque vous évoquez le C/C++, le C n'a que du passage par valeur (bien qu'il puisse passer des adresses comme avec les pointeurs mais aussi les tableaux) alors que le C++ possède en plus un passage par référence.
De plus, le fait de passer une adresse ne rend en rien le contenu modifiable, cas des "string" (typeof) en Javascript dont c'est sans doute l'adresse qui est passée mais qui ne sont pas modifiables pour autant.
Mon erreur d'interprétation vient de ce que, dans un langage ne possédant qu'un passage par valeur, que l'on puisse passer l'adresse d'un objet ou son contenu n'a pas d'impact. Cela relève de l'implémentation. Ce qui relève du langage c'est est-ce que je peux modifier le contenu et que cette modification soit répercutée dans l'environnement de l'appelant. Ce qui était, je crois le sens de la question.
Il me semblait que sématiquement, il était important de distinguer des fonctions déclarées
(bien que & n'existe pas en Javascript, c'est juste un exemple)
deCode:function f ( &x ) { ... };
car dans les deux cas l'appel s'écrit de la même façon, mais n'a pas le même sens.Code:function f ( x ) { ... };
On est au niveau du langage. Savoir si c'est une adresse qui est passée ou pas est au niveau de l'implémentation. Par exemple, j'utilise Rhino comme moteur ES5, qui est écrit en Java, qui est transformé en bytecode pour la JVM sur une plateforme Windows. Comment mon argument Javascript est réellement passé à ma fonction ? je n'en sais rien.Code:f(a);
encore une fois je conseille de lire la théorie des langages
dans la théorie de langage
soit deux variable A, B qui référencent le même objet (string int tab etc. peu importe sa nature)
lors d'un passage par valeur de la variable A seul le contenu de la zone mémoire référencé par la variable est trans mis à la fonction
si la fonction modifie ce contenu qui lui a été passé
le contenu de la zone mémoire référencé par les variable A et B n'a pas changé.
lors d'un passage par référence de la variable A c'est la référence de la zone mémoire contenant les donnée qui est transmise. si la fonction modifie ce contenu qui lui a été passé
le contenu de la zone mémoire référencé par les variable A et B n'a a changé et on peut le vérifier en inspectant le contenu référencé par B
lors d'un passage par pointeur de la variable A c'est une référence à la zone mémoire contenant A et non pas la zone référencé par A qui est transmise.
si la fonction affecte un nouvel objet à son paramètre
Le contenu de la zone référencé par B n'a pas changé
Mais A référence une nouvelle zone.
Je crois que tu confonds la variable et l'objet référencé par la variable.
en C++ lorsque tu faisil n'y a rien en mémoire qui représente la variable A elle n'existe que dans le langage et le compilateur remplace le symbole A par l'offset de la zone allouée pour le char[5]Code:char[5] A;
A référence une zone char[5] et seule cette zone existe en mémoire. (il est nécessaire de compiler avec des option de debug pour que le compilateur ajoute dans le codé généré une table d'association contenant le symbole A et l'offset de la zone char[5];
A et une variable char[5] l'objet qu'elle référence.
si tu fais si tu passe A par référence à une fonction tu passe l'offset associé à A le contenu de char[5] peut être modifié
mais A référence toujours la même zone mémoire.
pour pouvoir changer la zone que référence A il faut utiliser un pointeurcette fois le compilateur va créer deux zone un mot mémoire qui est le pointeur et une zone pour le char[5]Code:char[5] *A;
lorsque tu passe la variable A tu passe l'offset de A cet a dire le mot mémoire. si tu change la valeur de ce mot ton point référencera une nouvelle zone char[5]
le passage par référence c'est comme si je te donnais les infos d'un ami contenu dans mon carnet d'adresse.
ces infos te permettent de retrouver mon ami et fêter avec lui son anniversaire.
tu aura donc changé les informations de notre ami.
mais mon carnet d'adresse continuera à le référencer. (I.E. les infos de mon carnet permettent de le retrouver)
ce l'est pas la même chose que de te donner la possibilité de changer le contenu de mon carnet d'adresse.
Je pense que ce qui te pose problème avec javascript c'est qu'e si tu modifie une string dans ta fonction la variable ne semble pas affecté.
en javascript les String son non modifiable. on peut créer d'autre string avec les opérateurs et les fonctions mais on ne modifie jamais une string.
Mais en fait tu ne modifie jamais une string toute les opération sur les strings créent une nouvelle string.
tu viens de créer 3 strings.Code:
1
2
3 a = 'test'; b = 'truc'; c = a + b;
la encore tu crée 3 strings (b et p seront détruite immédiatement mais elle sont tout de même créées.Code:
1
2
3
4
5
6 a='test'; function (p) { b = 'truc'; p = p + b; } f(a);
A+JYT
probablement par copie pour les types primitifs (ou const référence si on délègue l'instanciation de copie dans la fonction)Code:Comment mon argument Javascript est réellement passé à ma fonction
par valeur pour les autres types si ces autres types sont des pointeurs
par référence si ces autres types sont des objets pleins.:mouarf:
edit: même pas const ref, à cause de string[2]='c' qui modifie la string
Miam miam (passage par référence)
Oooh (passage par valeur)Code:
1
2 void b ( int &score ) { score++; } b(ton_score);
:DCode:
1
2 function b ( score ) { score++; } b(ton_score);
mais ce n'est pas ça qu'il veux
il vaut faire ça;
il veut que la fonction désalloue la mémoire référencé par test, alloue une autre zone et que test référence la nouvelle valeurCode:
1
2
3
4
5
6 void b ( char[] &score ) { score="abcd"; //on affecte une nouvelle valeur au paramètre } char[] test = "wxyz"; b(test); printf(fest);// abcd
il voudrait que ça fasse ça. sauf qu'en javascript les string sont inmutablece que visiblement il ne comprends pas c'est que lorsqu'il fait un passage par référence il se passe ça:Code:
1
2
3
4
5
6
7
8
9 void b ( char[] &score ) { score[0]='a'; //on change le contenu de la zone référencé par le paramètre score[1]='b'; score[2]='c'; score[3]='d'; } char[] test = "wxyz"; b(test); printf(fest);// abcd
car c'est exactement ce qu'il se passe en javascript. il affecte une nouvelle valeur à son paramètre et ne change pas le contenu de l'objet.Code:
1
2
3
4
5
6
7
8 char[] a = "wxyz"; char[] b = "abcd"; char[] c = &a; //passage du paramètre c référence le tableau référencé par a //il veut que l'affectation suivante modifie a c = &b; //c référence maintenant le tableau référencé par b //il veux que a contienne abcd printf(a); //a n'a pas changé. il a simplement changé la référence de c mais il n'a touché à aucun contenu
ce qui est la s'écrit en js
A+JYTCode:
1
2
3
4
5
6
7
8 var a = "wxyz"; var b = "abcd"; var c = a; //passage du paramètre c référence le tableau référencé par a //il veut que l'affectation suivante modifie a c = b; //c référence maintenant le tableau référencé par b //il veux que a contienne abcd mais a n'a jamais changé. console.log(a);
Tu passe l'adresse mémoire de ton_score dans la fonction et tu modifie le contenu de cette adresse, et comme en js les pointeurs n’existent pas, il n'y a pas d'équivalent.
Tu passe la valeur de la variable ton_score comme paramètre de ta fonction.Citation:
Oooh (passage par valeur)
:DCode:
1
2 function b ( score ) { score++; } b(ton_score);
Les pointeurs n’existent pas dans javascript, pour palier à ça et passer en référence des types primitifs, il y a un nombre infini de solution. Faut comparer ce qui est comparable...
PS : en ce qui concerne les tableaux, en C la taille des array doivent être indiqués à la définition car à la compilation la zone mémoire est réservée pour ce même tableau (ce qui n'a rien à voir avec des constantes de compilations car celle-ci sont interprétées par le compilateur et remplacées par leurs valeurs respectives, en dur, dans le code machine, pas dans la zone mémoire allouée aux variables).
Lorsqu'on souhaite utiliser un tableau à taille dynamique on peut alors utiliser des listes, qui pour chaque item ajoute l'adresse de l'itération suivante de la liste (qui peut se trouver n'importe où ailleurs en zone mémoire).
Tout ça pour dire que comparer array en js et array en C (en terme d'adressage mémoire) n'a absolument aucun sens.
lorsqu'on défini un variable dans n'importe quel langage on défini deux chose
un symbole qui va permettre de manipuler l'élément qu'il représente
et une zone mémoire.
Dans le cas d'un entier en javascript tout comme en c cet entier est représenté en mémoire par un mot mémoire (32b ou 64b)
dans un langage compilé le symbole n'existe que lors de la compilation (or options de debug)
dans le cas de javascript il existe en mémoire une table associative qui contient le symbole, son type, et une référence au mot mémoire contenant la valeur.
Dans le cas d'une chaine en javascript tout comme en c la chaine est représenté en mémoire par une suite de mots mémoire terminé par un 0
en javascript la variable et présente dans la table des symboles. cette table contient le nom de la variable le type et l'adresse en mémoire de la chaine.
l'orsqu'on passe l'entier par référence on passe son adresse. on ne passe pas la valeur contenue à cette adresse.
en C si on a compilé avec les options de debug on a en mémoire une table des symboles exactement comme en javascript.
si la fonction modifie l'entier suite à un passage par référence la variable n'a pas changé d'adresse.
c'est exactement ce qu'il se passe avec javascript pour les chaines.
une chaine de caractères en javascript n'est pas modifiable.
l'orsqu'on passe la chaine par référence on passe son adresse. on ne passe pas la valeur contenue à cette adresse.
si la fonction alloue une autre zone mémoire pour créer une autre chaine
la variable n'a pas changé d'adresse.
quelque soit le langage un passage par référence ne permet pas de changer la référence mais seulement ce qui est contenu à l'endroit référencé.
et comme en javascript les strings (pas les variable référençant des strings) ne sont pas modifiables une fonction ne peut pas modifier le contenu d'une string.
il se trouve qu'en javascript les type primitifs nombre et boolean sont toujours passé par valeur.
pour optimiser l'espace et les traitements au lieu pour un entier d'avoir une entrée dans la table qui contient le nom de la variable son type et l'adresse du mot mémoire contenant l'entier
la table des symbole contient le nom de la variable son type et l'entier directement.
ainsi pour les types primitif on fait l'économie d'une référence (ce qui facilite la libération de la mémoire) mais surtout
l'appel de fonction se fait toujours de la même façon
on passe à la fonction ce qui se trouve dans la table de symbole.
si c'est un type primitf la table contient la valeur ce sera donc un passage par valeur.
si c'est un type complexe la table contient l'adresse de l'objet ce sera donc un passage par référence.
comparé à C/C++ cela limite grandement les possibilités.
Mais du coup pour l'interprète c'est du systématique ce qui implique moins d'analyse moins de traitement.
quoi qu'il arrive que ce soit en javascript ou en C/C++ jamais une fonction ne pourra modifier le contenu de la table des symbole au travers d'une simple affectation de valeur.
A+JYT
On ne se comprend pas.
C++
L'appel des deux fonctions f0 et f1 est le même mais le résultat est trés différent.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 int deux = 2; // passage par valeur d'un entier void f0 ( int x ) { x = 2; } // passage par référence d'un entier void f1 ( int& x ) { x = 2; } // passage par valeur d'un pointeur sur un entier void f2 ( int *x ) { *x = 2; } // idem f2 void f3 ( int *x ) { x = &deux; } int main(int argc, char* argv[]) { int exitcode = 0; int a; a = 1; f0(a); // a == 1 a = 1; f1(a); // a == 2 a = 1; f2(&a); // a == 2 a = 1; f3(&a); // a == 1 return exitcode; }
L'appel de f1 et f2 est différent, mais le résultat est le même.
f3 n'est là que pour montrer que passer même un pointeur par valeur n'est pas la même chose qu'un passage par référence.
Le fait de passer une adresse où pas ne transforme pas un passage par valeur en passage par référence. Les sémantiques des appels sont différentes.
En Javascript, indépendamment du type de l'élément passé, le modèle s'apparente plus à un passage par valeur où certains types de données seraient des pointeurs (string, Object) que de celui d'un passage par référence permettant d'écrire une fonction comme f1.
Donc, à la question initialement posée :
la réponse est non. Le langage ne permet pas de spécifier ce type de passage.Citation:
Je voudrais savoir s'il est possible de passer par reference un argument en javascript ?
Maintenant, si vous posez la question :
est-ce que certains types de données sont passés par référence ?
la réponse peut-être oui, même si je considère que c'est plus un passage de pointeur par valeur.
si tu lis la spec, tu as tout un barda notamment sur les references.Code:En Javascript, indépendamment du type de l'élément passé, le modèle s'apparente plus à un passage par valeur où certains types de données seraient des pointeurs (string, Object) que de celui d'un passage par référence permettant d'écrire une fonction comme f1.
toutes les variables sont des références.
Quand tu passes une variable à une fonction, tu lui passes une référence.
Donc si tu veux, à l'implémentation du moteur js, le passage se fait par valeur mais au final tu passes quand même une référence (fonctionnellement parlant).
Le si tu veux, il est important, car rien ne t'interdis de passer une référence (au sens pointeur) si ca te plait. C'est un détail technique.
La question plus intéressante car j'imagine que tout le monde sait que les objets sont ... des ref, et qu'ils seront modifiés au sein de la fonction c'est la gestion des types primitifs.
à savoir:
someFunc('test')
il y aura-t-il création d'une ref pointant vers 'test' où bien une copie pure et dure de 'test'.
Tout laisse supposer le premier cas, mais pour y répondre, il faut bouffer du v8 (ou ses camarades)
On se comprends très bien sur le passage par référence
ce que tu comprends pas ces que tu ne change pas l'emplacement en mémoire de ton entier
en javascript l'entier est passé par valeur on ne peux pas le passer par référence.
en C++
ton entier deux est à un emplacement mémoire par exemple @256Code:
1
2
3
4
5 int deux = 2; // passage par référence d'un entier void f1 ( int& x ) { x = 2; }
tu appelle ta fonction en passant la référence.
ta fonction va modifier la valeur ce trouvant dans la case @256
deux n'a pas changé de place en mémoire il est toujours à l'emplacement @256
lorsque tu faistout comme pour ton entier maChaine est à un emplacement mémoire par exemple @2678Code:
1
2
3
4
5 String maChaine = new String("test"); // passage par référence d'une String void f1 ( String& x ) { x = new String("toto"); }
tu appelle ta fonction en passant la référence.
ta fonction peut modifier la valeur ce trouvant dans la case @2678
mais le corps de la fonction affecte une nouvelle chaine @9845 à x elle ne modifie pas la valeur contenu à l'adresse @2678
maChaine n'a pas changé de place en mémoire
avant l'appel on a les symboles suivant
maChaine -> @2678 'test'
appel de la fonction avant l'instruction on a les symboles
maChaine -> @2678 'test'
x -> @2678 'test'
on exécute le corps de la fonction on a
maChaine -> @2678 'test'
x -> @9845 'toto
on quitte a fonction le symbole x n'existe plus
maChaine -> @2678 'test'
ma Chaine n'a pas changé.
c'est simplement parce que dans le corps de ta fonction tu affecte une nouvelle référence au paramètre tu ne modifie pas le contenu référencé.
tu as donc bien passé ta variable par référence mais tu n'a pas comme pour ton entier changé son contenu.
de puis le début tu attends un effet que tu n'obtiens pas non pas parce que les variable sont passé par valeur mais parce que le corps de ta fonction ne fait pas ce que tu veux.
en C++
Dans les deux cas tu passe la variable par référence.Code:
1
2
3
4
5
6
7
8
9
10 Person salaryMan = new String("jhon", 35); // passage par référence d'un objet Person void birthday ( Person& x ) { x.age++; } // passage par référence d'un objet Person void replace ( Person& x ) { x = new Person("thom", 25); }
après l'appel de birthday salaryMan a un an de plus
après l'appel de replace salaryMan n'a pas changé
en javascriptDans les deux cas tu passe la variable par référence.Code:
1
2
3
4
5
6
7
8
9
10 salaryMan ={nom:"jhon", age:35}; // passage par référence d'un objet Person void birthday ( x ) { x.age++; } // passage par référence d'un objet Person void replace ( x ) { x = {nom:"thom", age:25}; }
après l'appel de birthday salaryMan a un an de plus
après l'appel de replace salaryMan n'a pas changé
ce que tu fais avec ta string c'est la fonction replace qui n'a aucune chance de modifier la variable.
tu ne changera jamais l'adresse référencé par une variable dans une fonction si tu passe le paramètre par référence.
tu ne peux que modifier ce qui est contenu à l'adresse qu'on te donne.
si je te dis prends mon cahier et sur la 4 page 3 ligne tu as le texte de l'exercice.
tu te rends à cette page et tu lit le texte et tu note sur ton brouillon
et tu notes page 4 ligne 3
puis tu efface cette référence et tu écris page 25 ligne 32
je reprends le cahier lorsque tu a fini et je constate qu'a la page 4 ligne 3 rien n'a changé.
pourtant je ne t'ai pas donné le texte mais un référence pour le trouver.
si tu avais modifié le texte à la ligne 3 page 4 j'aurais vu la modification.
Ce n'est pas un problème de passage par référence c'est un problème d'affectation de référence.
dans la fonction tu pense affecter une valeur string à la variable mais en fait tu affecte une nouvelle référence.
A+JYT
PS sorry pour les erreur de syntaxe C++ il y a longtemps que je n'ai pratiqué.
il y a création d'une référence.
mais de toute façon la fonction ne peux pas modifier la string les String son inmutable.
en javascriptpour tout les type primitif a reçoit la valeur référencé par bCode:a=b;
pour tout les autre type a reçoit la référence à l'objet référencé par a
ceci est vrai dans toute les affectations
le passage de paramètre n'est rien d'autre qu'une affectation a un paramètre.
A+JYT
je vois pas ce qui te permet d'assurer qu'il y a création de référence dans ce cas précis.Citation:
il y a création d'une référence.
mais de toute façon la fonction ne peux pas modifier la string les String son inmutable.
on peut très bien imaginer que la référence est créée pour un primitif dès qu'on essaie de l'assigner à une variable.
idem elle n'est pas forcément crée si dans la fonction on ne s'en sert pas.
Un cas peu probable, pas très productif, mais un cas quand même!
non en javascript les type primitif ne sont jamais traité par référence il le sont par valeur
et pour les type complexe il sont toujours traité par référence.
peut importe la définition de la fonction en javascript ce n'est pas la signature de la fonction qui détermine le fonctionnement d'un appel.
c'est le moteur javascript
lorsque tu appelles une fonction en passant un string
une référence à cette chaine est placée dans la liste des arguments et cela même si dans la définition il n'y a pas d'argument
c'est un peut comme si toute les définition de fonction avaient une signature java comme ça
Donc quoi qu'il arrive lorsque tu faisCode:
1
2 Object f(Object... args) { }
l'interprète mets 'toto" quelque part dans la mémoire puis il ajout l'adresse de cette String dans la liste args.Code:f('toto');
pour les types primitifs
les valeur sont directement stockés dans la table des symboles (on a à faire à un interprète, il faut la conserver en mémoire)
un appel de fonction consiste à créer un contexte d'exécution.
relier celui-ci au contexte qui fait l'appel (porté des variable en js)
ajouter le symbole args à ce contexte
placer dans args toutes les valeurs des types primitifs passés dans l'appel
placer dans args toutes les références des types complexes passé dans l'appel
définir un symbole correspondant à chaque nom d'argument de la définition de la fonction dans le contexte
relier chaque symbole à l'argument correspondant (par valeur pour les primitif, par référence pour les autres)
commencer l'exécution du corps de la fonction.
ce mécanisme est systématique il n'y aucun dérogation. le passage des arguments dans args ne dépends que de l'appel
la création des symboles ne dépends que de la définition de la fonction.
l'association des deux ne dépends que de leur présence dans le contexte.
il s'agit donc à chaque fois de parcourir une liste (d'élément passé dans l'appel pour args, de symbole dans la signature pour les nom de paramètre, des symbole dans le contexte pour l'association)
pas de dérogation pas de condition. un traitement simple prédéfini systématique.
ce qui est couteux ceux sont les choix. un traitement conditionnel est toujours beaucoup plus couteux qu'un traitement systématique.
En C++ le compilateur va déterminer la façon dont seront passé les arguments. il n'en connait que deux par valeur et par référence. pour le passage par référence et le passage par valeur des int float et boolean il produit une séquence qui est toujours la même. ce code généré consiste à placer le contenu d'un cellule mémoire sur la pile d'exécution. (le args de javascript).
le passage par valeur des types complexes demande au compilateur plus de travail. il faut qui détermine si le contenu doit être copié ou s'il peut se permettre d'optimiser est passer une référence. une fois ce choix fait il produit soit un code qui copie dans le tas la valeur du type complexe et il utilise cette référence soit il utilise directement la référence à l'objet.
puis la séquence de code généré est la même que pour le cas précédent.
mais c'est le compilateur qui le fait. cela est donc fait par le développeur avant que le produit ne soit livré. on peut donc se permettre de faire une analyse complexe et couteuse en temps. car ce qui en résultera sera un code efficace. de plus tout cela ne dépend que de la signature de la fonction
dans l'interprète javascript en javascript un tel traitement dépendrait de l'appel. il faudrait donc le faire à chaque appel.
on exécuterait donc un algo complexe qui ferait beaucoup d'opérations pour déterminer la meilleur stratégie. pour au final
faire très peut d'opérations pour réellement passe l'argument. ce sur coup se ferait à chaque appel de fonction. ce qui est énorme. avec un tel algo on aurait quelque chose qui prendre plus 90% à choisir quoi faire et 10% à le faire.
il est donc globalement plus efficace de toujours faire la même chose ce qui divise le temps par 10
même si parfois l'ors d'un appel une autre façon aurait fait gagné 1%
Si tu maitrise un minimum java tu peux facilement avec nashhorn ou rhino faire du pas à pas pour voir comment l'interprète travaille. tu verras que même si les implémentation son différentes que les techos sont différente les deux interprètes passent les arguments de la même façon.
Si tu maitrise C/C++ fait pareil avec Geko JascriptCore ou V8 tu verra là encore que les technos diffèrents que les implémentation diffèrent mais qu'il passent tous les paramètres de la même façon que Nashorn et rhino.
Une variable en javascript c'est trois trois mots dans une hashtable le premier point ver la string représentant son nom. le deuxième représente son type et le troisième contient une valeur simpleCitation:
Envoyé par galerien69
soit la valeur pour les Number et Boolean, soit l'adresse de l'objet.
en javascript les valeur des type primitif sont donc stocké dans la table des symbole.
il ne viendrait à l'idée de personne lorsqu'il a besoin d'une variable int de créer un variable de type référence à un int
puis créer le int et enfin affecter la référence à la variable.
non seulement ça rendrait le code complexe pour la suite vu qu'on a une référence et pas une variable. mais c'est inutile. javascript est restrictif sur les choix il ne te permet que de faireCode:
1
2
3
4
5
6 //pour faire int i =0; //on ne fait surtout pas int &i; int j = 0; i =&j;
et rien d'autre.Code:int i =0;
si il s'agit la d'un problème d'optimisation globale. il suffit de voir le temps de compilation d'un programme C/C++Citation:
Envoyé par galerien69
ce temps dans un interprète s'il appliquait les mêmes méthode se ferait systématiquement à tout les appels. soit des centaine de millier de fois. mieux vaut systématiquement créer la chaine dans le tas et passer une référence à la fonction que de dépenser des milliers de cycle d'horloge d'introduire des ruptures du pipeline pour voir si on peut en gagner quelque centaines.
c'est toujours vrai dans tout processus.
si tu trouve un algo sytématique qui dans 10 ou 20 % des cas n'est pas optimal
mieux vaut l'utiliser que d'utiliser un algo complexe qui dans tout les cas introduira 10% de temps de traitement en plus.
A+JYT
Merci sekaijin ! :D
Et histoire d'enfoncer le clou
Donc,Citation:
peut importe la définition de la fonction en javascript ce n'est pas la signature de la fonction qui détermine le fonctionnement d'un appel
c'est non ! :DCitation:
Je voudrais savoir s'il est possible de passer par reference un argument en javascript ?
Mais, est-ce que certains types de données sont passés par référence ?
c'est oui. (bien que je maintienne qu"en terme de représentation on est plus proche d'un passage par ... bon, allez je lache l'affaire :D)
http://www.ecma-international.org/ecma-262/5.1/#sec-8.7
Donc déjà non. Ca c'est implem dependant.Citation:
Une variable en javascript c'est trois trois mots dans une hashtable le premier point ver la string représentant son nom. le deuxième représente son type et le troisième contient une valeur simple
soit la valeur pour les Number et Boolean, soit l'adresse de l'objet.
Une variable c'est une référence, et une référence c'est bien trois trucs en table mais juste le nom, la valeur et un flag pour strict mode. valuer qui est primitive ou pas
Pareil il n'est nulle part fait mension de table des symboles c'est encore implem dependant.Citation:
en javascript les valeur des type primitif sont donc stocké dans la table des symbole.
et pourtant c'est le cas.Citation:
il ne viendrait à l'idée de personne lorsqu'il a besoin d'une variable int de créer un variable de type référence à un int
puis créer le int et enfin affecter la référence à la variable.
quand tu écris var i = 10
tu crées une référence de nom 'i', dont la base vaut Number(10).
Je peux me tromper, mais de manière générale, je préférence me fier à la spec qu'à un reverse de moteur js. (aussi pertinent soit-il)Citation:
For example, the left-hand operand of an assignment is expected to produce a reference
ps:
juste pour la mémoire, &i est invalide il manque un = qqch.Citation:
//on ne fait surtout pas
int &i;
est invalide
De manière générale on parle pas de référence C++, mais de référence js.
On peut implem une référence avec la hashtable, c'est probablement le cas (j'ai jamais eu la curiosité) mais savoir si on store le type et la valeur ou bien juste un objet primitif ou pas, c'est au choix..
la spec est écrite pour tenir compte des perfs, mais les algos mis en place pour des raisons de perf ne constituent pas la spec!Citation:
si tu trouve un algo sytématique qui dans 10 ou 20 % des cas n'est pas optimal
mieux vaut l'utiliser que d'utiliser un algo complexe qui dans tout les cas introduira 10% de temps de traitement en plus.
Typiquement, si tu crées une ref de string quand tu la passes à la fonction, ok pour les raisons de perf, mais si c'est pas speccé ya rien qui t'oblige à faire ainsi.
Bon ici, c'est vrai que ya quand même arguments dans l'histoire, et pe que dans arguments sont storés des ref (je sais pas j'ai pas lu)
bref quelquepart on s'en tape un peu de comment le moteur est implémenté si la question porte sur du js (sans aborder les perfs liées d'écriture du js)
non la table des symbole est une obligation pour compiler ou interpréter un langage.Citation:
Envoyé par galerien69
dans un langage compilé, il est nécessaire de la conserver tout le temps de la compilation, ensuite seule les référence peuvent être utilisé et cela ne dépend que du compilateur et des specs du langage.
pour un langage interprété pour que le moteur lorsqu'il rencontre un symbole dans le code source sache à quoi celui fait référence il est nécessaire de conserver une association entre le texte représentant le symbole et l'objet que référence le symbole. donc non c'est purement théorique c'est une nécessité de l'interprétation.
libre au développeur de choisir son implémentation. la table doit exister c'est tout peu importe sa forme.
La encore NON en javascript Number(10) et 10 sont deux chose différente Number(10) est un objet don un membre contient 10 qui possède d'autres membres c'est donc une structure complexe faite de plusieurs cellules mémoiresCitation:
Envoyé par galerien69
et si on l'affecte à une variable il le sera par référence. alors que 10 est une seule cellule qui sera affecté par valeur.
donc respectons la spec tout affectation de type primitif se fait par valeurCitation:
Envoyé par galerien69
toute affectation de type complexe se fait par référence.
Jamais en javascript on ne va crée dans le tas de nombre ou de booléen pour affecter l'adresse de cet int ou de ce booléen à une variable.
Jamais en javascript on ne passera un objet complexe à une fonction par valeur.
Tu peux vouloir imaginer ce que tu veux javascript est défini ainsi.
A+JYT
et pourtant sur le moteur V8 :Citation:
Envoyé par sekaijin
8-)Code:
1
2
3
4
5
6
7
8
9
10
11
12
13 C:\Work>node > function inc(x) { x++; x.lastInc = new Date();} undefined > var a = new Number(10); undefined > a {} > inc(a) undefined > +a 10 > a {}
Je pense que l'auteur de ce thread c'est déjà pendu :mouarf:
ne me fais pas dire ce que j'ai pas dit:
Je n'ai pas dit que la table n'existe pas. J'ai dit qu'on l'implémente comme on veut.
on est d'accord sur ce point (ce que je contestais dans mon précédent message, c'est que tu déclares comme vérité établie que la hashtable doit contenir précisément type et valeur alors qu'on représente ca comme on veut)Citation:
libre au développeur de choisir son implémentation.
non, 10 est de type Number.Citation:
La encore NON en javascript Number(10) et 10 sont deux chose différente Number(10) est un objet
Number(10) est également de type Number (qui est un type primitif et qui vaut 10)
A ne pas confondre avec new Number qui effectivement est un object
Pourquoi parler de celulles mémoires!!!Citation:
c'est donc une structure complexe faite de plusieurs cellules mémoires
où as-tu lu ca?Citation:
donc respectons la spec tout affectation de type primitif se fait par valeur
11.2.3 Function Calls
- Let ref be the result of evaluating MemberExpression.
- Let func be GetValue(ref).
- Let argList be the result of evaluating Arguments, producing an internal list of argument values (see 11.2.4).
- ...
11.2.4 Argument Lists
- Let ref be the result of evaluating AssignmentExpression.
- Let arg be GetValue(ref). (see 8.7.1)
- Return a List whose sole item is arg.
8.7.1 GetValue (V)
- If Type(V) is not Reference, return V.
- ...
donc si type n'est pas une référence on passe la valeur
A+
PS: il est nécessaire de conserver le type dans la table des symboles car l'interprète en a besoin pour le transtypage lors de l'utilisation de certains opérateur comme + et le type peux changer au fil du temps. on garde donc toujours un contenu ref ou value et le type de ce contenu.
A+JYT
@pegase: l'opérateur ++ fait un cast en primitive Number, c'est pour ça qu'on perd la référence. Il faudrait trouver le moyen d'aller modifier la propriété interne [[PrimitiveValue]] pour garder la référence, mais ça je sais pas comment on fait. Et puis ça n'a pas beaucoup d'intérêt en fait :mouarf:
Je suis impressionné par la tournure que prend cette conversation 8O
Je crois que le mieux pour avoir la réponse à la question est de tester différents langages pour se convaincre soi-même.
Sachant que le terme « référence » (avec une bonne grosse paire de guillemets) représente différents concepts et que, apparemment, on n'est pas tous d'accord sur lequel.
Pour moi il y a seulement deux concepts :
– Concept « référence Java » : la VM ou l'interpréteur choisit la façon de passer l'argument en fonction de son type. Un type primitif est passé par valeur (a.k.a. par copie) ; un type complexe est passé par référence. Le développeur n'a pas de contrôle sur ce mécanisme. C'est ce qui se passe en JavaScript.
– Concept « référence C++ » : on active ce mécanisme en utilisant le symbole & associé à un type, par exemple int&. C'est ce qui se passe en PHP. L'avantage de cette version du concept est qu'on peut passer des types primitifs par référence, un entier dans mon exemple.
Reste à avoir duquel de ces deux concepts (ou d'un autre que je ne connais pas :P) Kouamé Josué voulait parler.
Honnêtement, je commence à m'inquiéter… :PCitation:
Envoyé par p3ga5e
Belle tentative ! mais le concept est le même dans les deux cas. La différence n'est pas conceptuelle, mais de savoir qui choisit le type du passage de l'argument. Ce que tu explique d'ailleurs trés bien :mouarf:
Et puis immutable passage par valeur tout ça, rien n'empêche de tricher
Code:
1
2
3
4
5
6
7 function inc(x) { if ( x instanceof Number ) { var y = 1+x; x.valueOf = function(){return y}; x.toString = function(){return ""+y}; } }
instancier des primitives ? tu veux dire par leurs équivalents objet ? Ben à rien 99% du temps, mais je m'en suis servi récemment (voir 3 topics en dessous: http://www.developpez.net/forums/d14...on-type-volee/)
Généralement on déconseille d'utiliser ces wrappers de primitives, parce que comme tu dis c'est un vrai nid à bugs (et encore, mon préféré c'est if(new Boolean(false)){ alert('wtf'); }). D'ailleurs ça n'a pas loupé, on m'a fait la remarque dans le topic ^^
Pour l'incrémentation, si tu veux que l'opération soit faite avant le renvoi de la valeur de retour, il faut mettre le "++" devant :
oui je sais, pourquoi faire simple quand on peut faire compliqué :mrgreen:Code:
1
2 var a = new Number(10); ++a; //11
Citation:
donc si type n'est pas une référence on passe la valeur
;)Citation:
à savoir:
someFunc('test')
il y aura-t-il création d'une ref pointant vers 'test' où bien une copie pure et dure de 'test'.
Tout laisse supposer le premier cas, mais pour y répondre, il faut bouffer du v8 (ou ses camarades)
Citation:
il y a création d'une référence.
(entre crochets c'est de moi, tu réfèrais à Number(10) mais Number(10) n'est pas un object)Citation:
si on l'affecte [l'objet] à une variable il le sera par référence.
alors que 10 est une seule cellule qui sera affecté par valeur.
il est également intéressant pour une affectation de regarder ce qu'il se passe lorsque l'on utilise un simple assignment
idem l'appel
on crée une ref de base primitive de valeur 10Code:var i = 10
mais également
que contient la base de j. une ref vers la base de i ou la valeur 10 ?Code:
1
2
3 var i=10 var j=i
je n'ai pas la réponse (mais j'espère un quote de la spec évidemment).
j contient la valeur 10, puisque c'est une primitive. Où est-ce que vous voulez en venir à la fin ? J'ai l'impression que vous avez fait trois fois le tour du sujet en employant des mots différents. Maintenant le nouveau mot c'est "base" :weird:
je veux en venir nulle part. Plutot que gober des trucs pré établis et observés (n'importe qui peut voir que tout se fait par valeur, les références semblant copiées..par valeur), c'est plus intéressant de voir si c'est le cas tout le temps et si oui qu'est-ce qui l'approuve.
de même pour un type primitif tu affirmes que j contient 10. Mais pourquoi. (pourquoi dans le sens qu'est-ce qui justifie une telle déclaration)
Pourquoi j ne contiendrait pas une ref à i. Et en utilisant j, la base de i étant un primitif, la base de j serait duppliquée?
le nouveau mot il est pas nouveau depuis le dernier poste.Citation:
Maintenant le nouveau mot c'est "base"
et quel est le problème d'utiliser des nouveaux mots à partir du moment où ils sont définis?:weird:
la réponse est dans la spec
celle-ci décrit bien comment on passe un argument
de même elle décrit comment se fait une affectation a une variable dans tous les cas
cela se passe au travers de 8.7.1 GetValue qui renvoie la valeur si le type n'est pas une référence.
Donc lorsque quelqu'un pose la question la réponse est
"Javascript utilise toujours des références pour tout ce qui n'est pas type primitif et des valeur dans le cas contraire"
vu que certains dans la discu ne comprenaient pas j'ai tenter d'expliquer comment fonctionne le moteur.
Mais c'est une définition du langage ce n'est pas un pb d'implémentation, ni de choix du développeur javascript.
C'est simplement dans la spec.
on peut le déplorer. on peut l'approuver. on peut imaginer ce que l'on veut. c'est la spec.
il n'y a rien a gober qui sortirait d'un chapeau. c'est la spec.
ce qui m'a fait réagir c'est que l'expérience décrite pour montrer que ce n'est pas un passage par référence était fausse.
Changer la référence d'une variable locale dans une fonction ne pourra jamais quelque soit le langage changer la référence d'une variable passé en paramètre.
la conclusion était donc fausse.
et il y a des vérités incontournable dans la théorie des langages.
lorsqu'on passe une valeur à une fonction on peut l'utiliser mais pas la modifier
lorsqu'on passe une référence à une valeur à une fonction on peut modifier la valeur mais pas la référence.
de plus dans cette discussion j'ai constaté beaucoup de confusions dans la définition de variable
toujours d'un point de vu purement théorique (donc indépendamment du l'implémentation) une variable c'est
un symbole, dans un contexte, associé à un type et une valeur.
même les langages les plus faiblement typé en passent par là.
et pour finir tout système d'analyse et de traitement lexical et sémantique a besoin de conserver l'ensemble des symboles.
c'est pour cette raison que cet ensemble est présent dans les compilateurs et aussi dans les interprètes. mais aussi dans les système de traduction ou d'analyse du langage naturel. c'est un problème purement algébrique un ensemble de terminaux + une grammaire produit des terminaux. c'est une condition nécessaire à la constitution d'un langage. (je sais je simplifie mais je ne vais pas mettre toute la théorie ici, il existe des bouquins pour ça)
A+JYT