2017-02-19 40 views
0

communauté Cher et assistants Javascript,Modulepattern et instances d'objets - changement inattendu de PropertyValues ​​

j'ai rencontré un comportement que je ne peux pas donner un sens.

Mon intention est de créer un module qui simule des variables privées et contrôle la création d'objets.

J'espère que l'exemple suivant illustre ce que je veux et quel est mon problème.

const ex = (() => { 
 

 
    // Creating the constructor for points 
 
    function Point() { 
 
    let x; 
 
    let y; 
 
    
 
    // I think using prototype is a good idea, because it can be expected that a lot of points are created. So I do not waste memory with a lot of function duplications. 
 
    Point.prototype.setX = xValue => { 
 
    x = xValue; 
 
    } 
 
    
 
    Point.prototype.setY = yValue => { 
 
    y = yValue; 
 
    } 
 
    
 
    Point.prototype.getY =() => { 
 
    return y; 
 
    } 
 
    } 
 
    
 
    // Returning an interface to create points 
 
    // but hide their properties. 
 
    return {createPoint: (x,y) => { 
 
    let point = new Point(); 
 
    point.setX(x); 
 
    point.setY(y); 
 
    return point; 
 
    }} 
 
})(); 
 

 

 

 
p1 = ex.createPoint(1,2); 
 
console.log(p1.getY()); // Result is '2' as expected 
 

 
p2 = ex.createPoint(3,4); 
 
console.log(p2.getY()); // Result is '4' as expected 
 

 
console.log(p1.getY()); // Result is '4'..Wait...'4' what? Why?!

Je pense que la source évidente est mon lac de comprendre la portée ... Mes hypothèses étaient/sont que si je crée une fonction comme prototype propriété: 1. La fonction est pour tous les objets du type créé visibles. 2. La fonction prototype fonctionne sur la portée de l'objet qui l'utilise. De mes résultats, je doute que le nombre 2 est correct.

Alors je lui ai donné un autre coup et affecté les propriétés et méthodes directement à l'objet nouvellement créé (je l'espère, je l'ai fait ...)

const ex = (() => { 
 

 
    // Creating the constructor for points 
 
    function Point() { 
 
    this.x; 
 
    this.y; 
 
    
 
    // I think using prototype is a good idea, because it can be expected that a lot of points are created. So I do not waste memory with a lot of function duplications. 
 
    this.setX = xValue => { 
 
    x = xValue; 
 
    } 
 
    
 
    this.setY = yValue => { 
 
    y = yValue; 
 
    } 
 
    
 
    this.getY =() => { 
 
    return y; 
 
    } 
 
    } 
 
    
 
    // Returning an interface to create points 
 
    // but hide their properties. 
 
    return {createPoint: (x,y) => { 
 
    let point = new Point(); 
 
    point.setX(x); 
 
    point.setY(y); 
 
    return point; 
 
    }} 
 
})(); 
 

 

 

 
p1 = ex.createPoint(1,2); 
 
console.log(p1.getY()); // Result is '2' as expected 
 

 
p2 = ex.createPoint(3,4); 
 
console.log(p2.getY()); // Result is '4' as expected 
 

 
console.log(p1.getY()); // Result is '4'..Wait...'4' what? Why?!

Mais le résultat n'a pas changer et je ne peux pas donner un sens au comportement. Après avoir relu les chapitres sur les fermetures et les prototypes dans ma js-bible, je ne sais pas où je peux chercher ou trouver de l'aide que de vous demander.

Je serais heureux si vous pourriez signaler mon erreur à moi et expliquer ce qui ne va pas dans mon code.

Amitiés

Jim

Répondre

0

Il y a quelques problèmes sur votre code:

  • La façon dont vous utilisez les fonctions de direction. Il n'y a pas d'objet 'this' dans les fonctions de flèches. Donc, les utiliser pour définir un prototype aura des résultats bizarres.

  • En parler? Ah oui, vous devez utiliser 'ceci' pour stocker une valeur quelque part dans l'instance de la classe.

  • Il semble qu'il n'y ait aucun problème à utiliser ES2015 (ES6) dans votre cas. Pourquoi ne pas utiliser ES2015's 'Class' pour définir une classe? (Elle ne vous donne pas non plus de réels accessoires privés, mais la syntaxe est très améliorée)

  • La création d'une instance de classe dans une fonction dans une autre fonction ou fermeture ne masque pas vraiment les propriétés de la classe. Puisque vous renvoyez cet objet, les valeurs peuvent être accessibles par dessus.

La sécurisation stricte des propriétés/méthodes privées des objets de classe n'est pas vraiment nécessaire.Il est conseillé de leur donner un préfixe (_ est commun) et à chaque fois que vous tapez ce préfixe sur votre code, n'utilisez cette variable que de manière privée.

const ex = (() => { 
 

 
    // Creating the constructor for points 
 
    function Point() { 
 
    }; 
 

 
    Point.prototype.setX = function(xValue) { 
 
    console.trace('hmm'); 
 
    this.x = xValue; 
 
    }; 
 

 
    Point.prototype.setY = function(yValue) { 
 
    this.y = yValue; 
 
    }; 
 

 
    Point.prototype.getY = function() { 
 
    return this.y; 
 
    }; 
 
    
 
    return { 
 
    createPoint: (x, y) => { 
 
     let point = new Point(); 
 
     point.setX(x); 
 
     point.setY(y); 
 
     return point; 
 
    } 
 
    } 
 
})(); 
 

 

 

 
const p1 = ex.createPoint(1, 2); 
 
console.log(p1.getY() + " (Result is '2' as expected)"); 
 

 
const p2 = ex.createPoint(3, 4); 
 
console.log(p2.getY() + " (Result is '4' as expected)"); 
 
console.log(p1.getY() + " (Result is '2' as expected)");

Et voici un exemple d'avoir une classe avec certains députés réels:

const Point = function(valueX, valueY) { 
 
    let x = valueX; 
 
    let y = valueY; 
 
    this.getY =() => { 
 
    return y; 
 
    }; 
 
}; 
 

 
const p1 = new Point(1, 2); 
 
console.log(p1.getY() + " (Result is '2' as expected)"); 
 

 
const p2 = new Point(3, 4); 
 
console.log(p2.getY() + " (Result is '4' as expected)"); 
 

 
console.log(p1.getY() + " (Result is '2' as expected)");

+0

Cher Bulent Vural, je vous remercie beaucoup pour votre répondre. Votre suggestion concernant les fonctions de la flèche est une aide précieuse et une nouvelle idée précieuse (= Votre solution proposée est sans aucun doute une amélioration, mais une fonctionnalité (qui fonctionnait auparavant pour un objet) a été perdue. par exemple, on peut y accéder directement avec p1.x (je suis désolé de ne pas l'avoir expliqué explicitement dans les codes), c'est pourquoi j'ai essayé dans ma première tentative 'let x' afin qu'ils soient cachés dans le scope. – Jim

+0

J'ai mis à jour ma réponse avec quelques infos supplémentaires Il y a des façons de rendre des membres vraiment privés, mais ça ne vaut vraiment pas la peine.J'ai mis un exemple quand même –

+0

Merci beaucoup Votre réponse a été très utile et est un bon point de sur lequel je peux travailler plus loin (= – Jim