2017-09-28 1 views
0

J'ai deux IFFE:Comment passer par référence ou imiter

var Helper = (function() { 
    return { 
     number: null, 
     init: function (num) { 
      number = num; 
     } 
    } 
})(); 

var Helper2 = (function() { 
    return { 
     options: { 
      number: [], 
     }, 
     init: function(num){ 
      this.options.number = num; 
     }, 
     getData: function() { 
      return this.options.number; 
     } 
    } 
})(); 


Helper2.init(Helper.number); 
console.log(Helper2.getData()); 
Helper.init(5); 
console.log(Helper2.getData()); 

Ce que je veux est

Helper2.init(Helper.number); 
console.log(Helper2.getData()); // null 
Helper.init(5); 
console.log(Helper2.getData()); // 5 

ce que je reçois est

Helper2.init(Helper.number); 
console.log(Helper2.getData()); // null 
Helper.init(5); 
console.log(Helper2.getData()); // null 

Quelles techniques peuvent faire le faire passer par référence, s'il le peut?

JSBIN: https://jsbin.com/gomakubeka/1/edit?js,console

Edit: Avant tonnes de gens commencent à intégrer différentes façons d'avoir Helper2 depend on Helper, la mise en œuvre effective de Helper est inconnu et pourrait avoir 100 de moyens qu'ils mettent en œuvre le nombre, donc Helper2 a besoin de l'adresse mémoire.

Edit 2: Je suppose que le chemin que j'espérais obtenir un certain départ sur était de savoir que les tableaux/objets ne soient passés par référence, comment puis-je envelopper ce type primitif de telle sorte que je peux utiliser par référence

+0

Ce qui est concret sur le code que vous avez? Quand vous dites qu'il y a 100 façons dont 'Helper' peut implémenter le nombre, cela signifie-t-il que le schéma courant est que' Helper' aura toujours un attribut sur la racine de l'objet qui est de type 'Number'? – zero298

+0

Pourquoi ne pas encapsuler Helper directement dans Helper2? –

+0

@ zero298 Oui. Il peut être dans une variable appelée '.randomNumber' dans quelqu'un elses implémentation de' Helper' @ Jean-BaptisteYunès J'aurais besoin d'une interface alors qui a un moyen commun d'obtenir la valeur que je veux, mais il n'y a pas d'interface (et il n'y a pas un moyen strict de le faire AFIK en js). – CuriousDeveloper

Répondre

0

Tout d'abord, pourquoi cela ne fonctionne-t-il pas:

helper est une fonction auto-activante qui retourne un objet. Lorsque init est appelé, il définit un nombre à l'objet Helper.

Ensuite, dans Helper2, vous passez un nombre entier (Helper.number) à init définissant l'objet sur null. Donc, vous ne passez pas la référence à Helper.number. Seule la valeur est définie.

Vous devez lui passer tout l'objet et le lire.

Un exemple:

var Helper = (function() { 
 
    return { 
 
     number: null, 
 
     init: function (num) { 
 
      this.number = num; //add this 
 
     } 
 
    } 
 
})(); 
 

 
var Helper2 = (function() { 
 
    return { 
 
     options: { 
 
      number: [], 
 
     }, 
 
     init: function(obj){ 
 
      
 
      this.options = obj; //save a reference to the helper obj. 
 
     }, 
 
     getData: function() { 
 
      if (this.options.number) 
 
      { 
 
       return this.options.number; 
 
      } 
 
     } 
 
    } 
 
})(); 
 

 

 
Helper2.init(Helper); //store the helper object 
 
console.log(Helper2.getData()); 
 
Helper.init(5); 
 
console.log(Helper2.getData());

+0

Cela dépend d'une certaine interface à laquelle Helper doit se conformer pour que Helper2 sache quelle est la variable nommée. Par exemple c'est possible que Helper.thisisthenumber soit là où le nombre que je veux est stocké. Malheureusement les interfaces ne sont pas quelque chose en javascript donc je n'ai pas de contrat entre les deux objets – CuriousDeveloper

+0

Vous avez raison. Il y a des solutions à cela. Si vous voulez que quelque chose soit générique, il faut plus de lignes de code. Regardez dans l'héritage du prototype. – Mouser

1

Passing par référence en JavaScript ne peut se produire à des objets. La seule chose que vous pouvez transmettre par valeur dans JavaScript sont les types de données primitifs. Si sur votre premier objet vous avez modifié le "nombre: nul" pour être imbriqué dans un objet d'options comme dans votre deuxième objet, vous pouvez passer une référence de cet objet à l'autre objet. L'astuce est si vous avez besoin de passer par référence pour utiliser des objets et non des types de données primitifs. Au lieu de cela, imbriquez les types de données primitifs dans les objets et utilisez les objets.

Je vous ai légèrement modifié le code mais je pense que cela fonctionne pour ce que vous essayiez d'obtenir.

var Helper = function (num) { 
 
    return { 
 
     options: { 
 
      number: num 
 
     }, 
 
     update: function (options) { 
 
      this.options = options; 
 
     } 
 
    } 
 
}; 
 

 
var Helper2 = function (num) { 
 
    return { 
 
     options: { 
 
      number: num, 
 
     }, 
 
     update: function(options){ 
 
      this.options = options; 
 
     }, 
 
     getData: function() { 
 
      return this.options.number; 
 
     } 
 
    } 
 
}; 
 

 
var tempHelp = new Helper(); 
 
var tempHelp2 = new Helper2(); 
 
tempHelp2.update(tempHelp.options); 
 
tempHelp.options.number = 5; 
 
console.log(tempHelp2.getData());

+0

Salut, bienvenue à SO. Grande réponse, a pris la liberté de mettre votre réponse dans un extrait de code afin que les gens puissent voir le résultat. – Mouser

+0

Merci, et merci de l'avoir placé dans un extrait de code. –

0

Je ne pense pas que vous allez être en mesure d'obtenir exactement ce que vous voulez.Cependant, dans un de vos commentaires, vous avez dit:

Malheureusement les interfaces ne sont pas quelque chose dans javascript

Ce n'est pas tout à fait vrai. Oui, il n'y a pas de typage fort et les utilisateurs de votre code sont libres d'ignorer complètement vos suggestions si vous dites qu'une fonction a besoin d'un type spécifique d'objet. Mais, vous pouvez toujours créer une interface de sortes à partir de laquelle vous voulez que les utilisateurs étendent afin de jouer bien avec votre propre code. Par exemple, vous pouvez dire aux utilisateurs qu'ils doivent extend de la classe Valuable avec un mécanisme pour accéder à une propriété calculée value qui sera une instance Reference pouvant encapsuler une primitive (résolvant le problème de ne pas pouvoir passer la primitive par référence) .

Comme cela utilise des propriétés calculées, cela a également l'avantage de tirer parti de la notation .value. La chose est que le .value sera un Reference au lieu de la valeur réelle.

// Intermediary class that can be passed around and hold primitives 
 
class Reference { 
 
    constructor(val) { 
 
    this.val = val; 
 
    } 
 
} 
 

 
// Interface that dictates "value" 
 
class Valuable { 
 
    constructor() { 
 
    this._value = new Reference(); 
 
    } 
 
    get value() { 
 
    return this._value; 
 
    } 
 
    set value(v) { 
 
    this._value.val = v; 
 
    } 
 
} 
 

 
// "Concrete" class that implements the Valuable interface 
 
class ValuableHelper extends Valuable { 
 
    constructor() { 
 
    super(); 
 
    } 
 
} 
 

 
// Class that will deal with a ValuableHelper 
 
class Helper { 
 
    constructor(n) { 
 
    this.options = { 
 
     number: n 
 
    } 
 
    } 
 
    getData() { 
 
    return this.options.number; 
 
    } 
 
    setData(n) { 
 
    this.options.number = n; 
 
    } 
 
} 
 

 
// Create our instances 
 
const vh = new ValuableHelper(), 
 
    hh = new Helper(vh.value); 
 

 
// Do our stuff 
 
console.log(hh.getData().val); 
 
vh.value = 5; 
 
console.log(hh.getData().val); 
 
hh.setData(vh.value); 
 
vh.value = 5;

+0

Je suis limité à ES5 mais je regarde ce qui est possible – CuriousDeveloper