53 votes

objet passer par référence

Je sais que dans JS, les objets sont passés par référence, par exemple:

 function test(obj) {
    obj.name = 'new name';
}

var my_obj = { name: 'foo' };
test(my_obj);
alert(my_obj.name); // new name
 

Mais pourquoi ne fonctionne pas ci-dessous:

 function test(obj) {
    obj = {};
}

var my_obj = { name: 'foo' };
test(my_obj);
alert(my_obj.name); // foo
 

J'ai mis l'objet à {} vide, mais il est toujours écrit foo .

Quelqu'un peut-il expliquer la logique derrière cela? Merci

67voto

Alexander Varwijk Points 1257

Si vous connaissez les pointeurs, c'est une analogie que vous pouvez prendre. En fait, vous passez un pointeur. Ainsi, obj.someProperty déréférencerait cette propriété et l'aurait annulée, alors que simplement remplacer obj tuerait le pointeur et n'écraserait pas l'objet.

30voto

Adam Rackis Points 45559

Parce que JavaScript passe en fait des objets par copie passe-sous - -Référence.

Lorsque vous transmettez my_obj à votre fonction test , une copie d'une référence à cet objet est transmise. Par conséquent, lorsque vous réaffectez l'objet dans test , vous ne faites en réalité que réaffecter une copie d' une référence à l'objet d'origine; votre my_obj reste inchangé.

27voto

Quentin Points 325526

Parce que vous écrasez la référence, pas l'objet.

 // Create a new object and assign a reference to it
// to the variable my_obj
var my_obj = { name: 'foo' };

// Pass the reference to the test function
test(my_obj);

// Assign the reference to a variable called obj
// (since that is the first argument)
function test(obj) {
// Create a new (empty) object and assign a reference to it to obj
// This replaces the existing REFERENCE
    obj = {};
}
// my_obj still has a reference to the original object, 
// because my_obj wasn't overwritten
alert(my_obj.name); // foo
 

5voto

Timo Points 2732

Javascript ne supporte pas le passage par référence (bien que les objets sont passés par référence et la référence est maintenue tant qu'il n'est pas écrasé avec affectation, par exemple. à l'aide de =), mais vous pouvez imiter ref de mots clés de C# à l'aide de la technique suivante:

function test(obj) {
  obj.Value = {};
  //obj.Value = {name:"changed"};
}

var my_obj = { name: 'foo' };

(function ()
{
  my_obj = {Value: my_obj};
  var $return = test(my_obj);
  my_obj = my_obj.Value;
  return $return;
}).call(this);

alert(my_obj.name); // undefined, as expected
                    // In the question this returns "foo" because
                    // assignment causes dereference

Bien sûr, vous pouvez utiliser des variables globales et d'appel de fonction sans arguments, auquel cas les références ne sont pas oubliée comme ceci:

var obj = { name: 'foo' };
function test() {
    obj = {};
}
test();
alert(obj.name); // undefined

Si vous avez tout votre code dans la fermeture, alors les choses sont plus simples et ci-dessus comme globals ne pas polluer l'espace de noms global:

(function(){
    var obj = { name: 'foo' };
    function test() {
        obj = {};
    }
    test();
    alert(obj.name); // undefined
}).call(this);

Ci-dessus "globals à l'intérieur de la fermeture de la technique est agréable, si vous avez du port, du Javascript un code C# qui a ref arguments. Par exemple. Le code C# suivant:

void MainLoop()
{
   // ...
   MyStruct pt1 = CreateMyStruct(1);
   MyStruct pt2 = CreateMyStruct(2);
   SwapPoints(ref pt1, ref pt2);
   // ...
}
void SwapPoints(ref MyStruct pt1, ref MyStruct pt2)
{
    MyStruct tmp = pt1;
    pt1 = pt2;
    pt2 = tmp;
}

il pourrait être porté à Javascript en utilisant quelque chose comme:

(function(){
    var pt1, pt2;
    function CreateMyStruct(myvar)
    {
      return {"myvar":myvar}  
    }
    function MainLoop()
    {
       // ...
       pt1 = CreateMyStruct(1);
       pt2 = CreateMyStruct(2);
       console.log("ORIG:",pt1,pt2); 
       SwapPoints(); 
       console.log("SWAPPED:",pt1,pt2);
       // ...
    }
    function SwapPoints()
    {
        var tmp = pt1;
        pt1 = pt2;
        pt2 = tmp;
    }
    MainLoop();

}).call(this);

ou si il est essentiel d'utiliser des variables locales et les arguments de la fonction, alors la solution peut être basé sur le premier exemple de ma réponse comme ceci:

(function(){
    function CreateMyStruct(myvar)
    {
      return {"myvar":myvar}  
    }
    function MainLoop()
    {
      // ...
      var pt1 = CreateMyStruct(1);
      var pt2 = CreateMyStruct(2);
      console.log("ORIG:",pt1,pt2); 

      (function ()
      {
        pt1 = {Value: pt1};
        pt2 = {Value: pt2};
        var $return = SwapPoints(pt1, pt2);
        pt1 = pt1.Value;
        pt2 = pt2.Value;
        return $return;
      }).call(this);

      console.log("SWAPPED:",pt1,pt2);
      // ...
    }
    function SwapPoints(pt1, pt2)
    {
      var tmp = pt1.Value;
      pt1.Value = pt2.Value;
      pt2.Value = tmp;
    }
    MainLoop();
}).call(this);

Vraiment dire que Javascript n'a pas beaucoup quand il n'a pas natif ref! Le code serait beaucoup plus simple.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X