IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

Passage d'argument à une fonction


Sujet :

JavaScript

  1. #1
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2013
    Messages
    120
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2013
    Messages : 120
    Points : 109
    Points
    109
    Par défaut Passage d'argument à une fonction
    Je voudrais savoir s'il est possible de passer par reference un argument en javascript . si oui comment procède t-on? Merci

  2. #2
    Membre habitué
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    125
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 125
    Points : 149
    Points
    149
    Par défaut
    Si je ne me trompe pas, les arguments en javascript sont tous passés en référence, hormis les types primitifs.
    A confirmer.

  3. #3
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 093
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 093
    Points : 6 754
    Points
    6 754
    Par défaut
    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 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    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.
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  4. #4
    Membre averti
    Profil pro
    à la bougie alors
    Inscrit en
    Mai 2006
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : à la bougie alors

    Informations forums :
    Inscription : Mai 2006
    Messages : 224
    Points : 362
    Points
    362
    Par défaut
    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.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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"
    Quels que soient les types et valeurs pour a et b.

  5. #5
    Membre confirmé
    Avatar de Darkaurora
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2010
    Messages
    382
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 382
    Points : 549
    Points
    549
    Billets dans le blog
    1
    Par défaut
    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
    Je préfère fermer ma gueule et passer pour un con que de l'ouvrir et ne laisser aucun doute à ce sujet.

  6. #6
    Membre expert
    Avatar de Golgotha
    Homme Profil pro
    Full-stack Web Developer
    Inscrit en
    Août 2007
    Messages
    1 385
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Full-stack Web Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2007
    Messages : 1 385
    Points : 3 527
    Points
    3 527
    Billets dans le blog
    1
    Par défaut
    Exemple avec un Objet :



    C'est bien l'adresse de l'objet qui est passée.
    Consultant et développeur full-stack spécialiste du Web
    faq jQuery - règles du forum - faqs web

  7. #7
    Expert éminent
    Avatar de sekaijin
    Homme Profil pro
    Urbaniste
    Inscrit en
    Juillet 2004
    Messages
    4 205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Urbaniste
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2004
    Messages : 4 205
    Points : 9 127
    Points
    9 127
    Par défaut
    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 objet
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        +--------+
    a ->|        |
        |  x:15  |
    b ->|        |
        +--------+
    Appel par valeur f(a); l'objet référencé par a et par b n'a pas changé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 objet
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        +--------+
    a ->|        |
        |  x:32  |
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        +--------+
    a ->|  x:32  |
        +--------+
     
        +--------+
    b ->|  x:15  |
        +--------+
    En Javascript seuls les passage par valeur pour les type primitifs et par référence pour tout le reste existe.

    A+JYT

  8. #8
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Citation Envoyé par Watilin Voir le message
    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.
    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.
    One Web to rule them all

  9. #9
    Membre émérite
    Avatar de Kaamo
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    1 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 1 165
    Points : 2 778
    Points
    2 778
    Par défaut
    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 php : Sélectionner tout - Visualiser dans une fenêtre à part
    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.

    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    J'ai ici pris 4, mais ça vaut pour toutes les primitives (voir ci-dessous la définition).

    Par contre, si tu passes un objet {} ou un array [] :
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    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 javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    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'}

    Vrai. Les types primitifs en JS sont les nombres et les booléens.
    Y'a un peu plus de types primitifs en réalité (selon la spéc) :
    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')

  10. #10
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 093
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 093
    Points : 6 754
    Points
    6 754
    Par défaut
    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.
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  11. #11
    Membre averti
    Profil pro
    à la bougie alors
    Inscrit en
    Mai 2006
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : à la bougie alors

    Informations forums :
    Inscription : Mai 2006
    Messages : 224
    Points : 362
    Points
    362
    Par défaut
    Kaamo avec sa fonction 'changeCoucou()' donne un excellent exemple de passage par référence.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $maVariable = 'coucou';
     
    function changeCoucou(&$a) {
        $a = 'toto';
    }
     
    changeCoucou($maVariable);
    // $maVariable vaut maintenant 'toto'
    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).

    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.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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])
    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.
    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

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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]
    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.
    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

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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]
    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'.

    En espérant avoir éclairci ce que je voulais dire

  12. #12
    Expert éminent
    Avatar de sekaijin
    Homme Profil pro
    Urbaniste
    Inscrit en
    Juillet 2004
    Messages
    4 205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Urbaniste
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2004
    Messages : 4 205
    Points : 9 127
    Points
    9 127
    Par défaut
    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 aurais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    @100             @115
    +-----+          +--------+
    |  a  |--------->|   15   |
    +-----+          +--------+
    @256             @271
    +-----+          +--------+
    |param|--------->|   15   |
    +-----+          +--------+
    dans le cas d'une String
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    @100             @115
    +-----+          +----------+
    |  a  |--------->|'Jhon Doe'|
    +-----+          +----------+
    en javascript on ne mets pas 'Jhon Doe' sur la pile mais on pets bien @115
    lorsque tu arrive dans ta fonction tu est dans la situation suivante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    @100             @115
    +-----+          +----------+
    |  a  |---+----->|'Jhon Doe'|
    +-----+   |      +----------+
    @256      |
    +-----+   |
    |param|---+
    +-----+
    tu a bien un référence à 'Jhon Doe'
    puis tu faisla variable param ne référence plus 'Jhon Doe' mais 'bill'
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    @100             @115
    +-----+          +----------+
    |  a  |--------->|'Jhon Doe'|
    +-----+          +----------+
    @256             @915
    +-----+          +--------+
    |param|--------->| 'bill' |
    +-----+          +--------+
    c'est exactement ce que fais javascript

    maintenant ce que ferait un passage par pointeur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    @256       @100            @115
    +-----+    +-----+         +----------+
    |param|--->|  a  |-------->|'Jhon Doe'|
    +-----+    +-----+         +----------+
    tu n'a plus de référence à l'objet référencé par a mais une référence à a lui-même.
    en utilisant la syntaxe adapté qui n'existe pas en javascript tu pourais faire un truc du genrepour obtenir
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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

  13. #13
    Membre averti
    Profil pro
    à la bougie alors
    Inscrit en
    Mai 2006
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : à la bougie alors

    Informations forums :
    Inscription : Mai 2006
    Messages : 224
    Points : 362
    Points
    362
    Par défaut
    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)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    function f ( &x ) { ... };
    de

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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.

    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.

  14. #14
    Expert éminent
    Avatar de sekaijin
    Homme Profil pro
    Urbaniste
    Inscrit en
    Juillet 2004
    Messages
    4 205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Urbaniste
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2004
    Messages : 4 205
    Points : 9 127
    Points
    9 127
    Par défaut
    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 fais il 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]
    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]
    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.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    a = 'test';
    b = 'truc';
    c = a + b;
    tu viens de créer 3 strings.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    a='test';
    function (p) {
     b = 'truc';
     p = p + b;
    }
    f(a);
    la encore tu crée 3 strings (b et p seront détruite immédiatement mais elle sont tout de même créées.

    A+JYT

  15. #15
    Invité
    Invité(e)
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Comment mon argument Javascript est réellement passé à ma fonction
    probablement par copie pour les types primitifs (ou const référence si on délègue l'instanciation de copie dans la 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.

    edit: même pas const ref, à cause de string[2]='c' qui modifie la string

  16. #16
    Membre averti
    Profil pro
    à la bougie alors
    Inscrit en
    Mai 2006
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : à la bougie alors

    Informations forums :
    Inscription : Mai 2006
    Messages : 224
    Points : 362
    Points
    362
    Par défaut
    Miam miam (passage par référence)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    void b ( int &score ) { score++; }
    b(ton_score);
    Oooh (passage par valeur)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    function b ( score ) { score++; }
    b(ton_score);

  17. #17
    Expert éminent
    Avatar de sekaijin
    Homme Profil pro
    Urbaniste
    Inscrit en
    Juillet 2004
    Messages
    4 205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Urbaniste
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2004
    Messages : 4 205
    Points : 9 127
    Points
    9 127
    Par défaut
    mais ce n'est pas ça qu'il veux
    il vaut faire ça;
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    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 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 valeur

    il voudrait que ça fasse ça. sauf qu'en javascript les string sont inmutable
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    ce que visiblement il ne comprends pas c'est que lorsqu'il fait un passage par référence il se passe ça:
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    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.
    ce qui est la s'écrit en js
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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);
    A+JYT

  18. #18
    Membre habitué
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    125
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 125
    Points : 149
    Points
    149
    Par défaut
    Citation Envoyé par lysandro Voir le message
    Miam miam (passage par référence)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    void b ( int &score ) { score++; }
    b(ton_score);
    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.

    Oooh (passage par valeur)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    function b ( score ) { score++; }
    b(ton_score);
    Tu passe la valeur de la variable ton_score comme paramètre de ta fonction.


    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.

  19. #19
    Expert éminent
    Avatar de sekaijin
    Homme Profil pro
    Urbaniste
    Inscrit en
    Juillet 2004
    Messages
    4 205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Urbaniste
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2004
    Messages : 4 205
    Points : 9 127
    Points
    9 127
    Par défaut
    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

  20. #20
    Membre averti
    Profil pro
    à la bougie alors
    Inscrit en
    Mai 2006
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : à la bougie alors

    Informations forums :
    Inscription : Mai 2006
    Messages : 224
    Points : 362
    Points
    362
    Par défaut
    On ne se comprend pas.

    C++
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 des deux fonctions f0 et f1 est le même mais le résultat est trés différent.
    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 :
    Je voudrais savoir s'il est possible de passer par reference un argument en javascript ?
    la réponse est non. Le langage ne permet pas de spécifier ce type de passage.

    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.

Discussions similaires

  1. Réponses: 4
    Dernier message: 29/04/2010, 06h30
  2. Passage de 'pipe' à une fonction ?
    Par laurent_ifips dans le forum POSIX
    Réponses: 2
    Dernier message: 25/11/2005, 07h06
  3. [JAVASCRIPT] passage d'argument à une fonction
    Par LE NEINDRE dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 03/06/2005, 18h17
  4. [TASM] Passage d'argument à une macro
    Par sorry60 dans le forum Assembleur
    Réponses: 13
    Dernier message: 23/04/2005, 18h22
  5. Passer une fonction comme argument à une fonction
    Par Cocotier974 dans le forum Général Python
    Réponses: 4
    Dernier message: 29/06/2004, 13h41

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo