2012-11-13 4 views
4

J'ai essayé d'apprendre la POO avec JavaScript avant de commencer à apprendre backbone.js. Je veux être capable de lier des données, mais je n'arrive pas à le faire fonctionner.Programmation JavaScript orientée objet

Je viens de faire un simple prototype d'un site Web à budget que vous pouvez mettre dans un budget et entrer combien vous avez dépensé, et il montrera si vous êtes passé.

function BudgetItem(spent, budget){ 

    this.setSpent = function(spent){ 
     this.spent = spent; 
    } 
    this.setBudget = function(budget){ 
     this.budget = budget; 
    } 
    this.getSpent = function(){ 
     return this.spent; 
    } 
    this.getBudget = function(){ 
     return this.budget; 
    } 

} 

function BudgetType(type){ 
    this.getType = function(){ 
     return type; 
    } 
} 

BudgetType.prototype = new BudgetItem(); 

$(document).ready(function(){ 

    var food = new BudgetType('food'); 

    $('.budget').html(food.getBudget()); 
    $('.editbudget').change(function(){ 
     food.setBudget($('.editbudget').data()) 
    }); 
}) 

C'est mon code jusqu'à présent. Je ne suis pas sûr si je le fais bien. Suis-je censé étendre les choses? En outre, quelqu'un peut-il expliquer comment lier dynamiquement des données sans bibliothèque?

+2

Vous ne avez pas besoin des fonctions getter/setter braindead, si vous avez besoin des fonctionnalités supplémentaires dans les plus tard, vous pouvez toujours les ajouter ensuite en tant que propriétés getter/setter et il fonctionnera de la même dans l'interface publique – Esailija

+0

Tout d'abord, je suggère de ne pas utiliser jQuery ou de telles bibliothèques jusqu'à ce que vous ayez une compréhension FIRM de JS. – SReject

+1

Cela ne répond pas à votre question, mais si vous essayez de maîtriser JS, OOP ou autre, vous devriez certainement lire [Javascript: The Good Parts] (http://www.amazon.com/exec/obidos/ ASIN/0596517742/wrrrldwideweb) par [Douglas Crockford] (http://crockford.com/). – prodigitalson

Répondre

5

D'abord, je vais vous donner un peu de théorie. Une fonction Javascript est un objet dynamique comme Object. Il a des propriétés et des méthodes et plus peut être ajouté à l'exécution (donc dynamique). Le mot-clé this est lié à l'objet nouvellement créé. Ainsi, ce que vous faites ci-dessus crée en fait de nouvelles propriétés à la volée lorsque vous transmettez leurs valeurs pour la première fois ... ce qui est bien, mais pas très clair pour un autre lecteur.

Chaque objet et chaque fonction créés par l'utilisateur ont un lien vers un objet prototype "caché". Il s'agit d'un objet anonyme (non accessible par nom) créé par l'environnement d'exécution JavaScript et transmis en tant que référence à l'objet utilisateur via la propriété prototype. L'objet Prototype a également une référence à l'objet utilisateur via sa propriété constructor. Tout mettre ensemble, vous pouvez maintenant penser à des fonctions en tant que constructeurs de classes qui ont été créées pour vous pour chaque fonction que vous avez et qui peuvent être accessibles via la propriété prototype de fonctions. Ainsi, vous pouvez ajouter les champs à l'objet prototype directement si:

function BudgetItem(spent) { 
    this.spent = spent 
}   
BudgetItem.prototype.spent = 0; 
BudgetItem.prototype.setSpent = function(spent) { this.spent = spent }; 
BudgetItem.prototype.getSpent = function(){ return this.spent }; 

Un autre problème est paramètres inheritence et passer au constructeur. Encore une fois, votre version est valide mais vous perdez la possibilité de transmettre les valeurs passées et budgétées lors de l'initialisation d'un BudgetType. Ce que je ferais, c'est oublier les prototypes et aller:

function BudgetType(type, spent) { 
    var instance = new BudgetItem(spent); 
    instance.type = type; 
    return instance; 
} 

Ceci est proche de ce que Scott Sauyet a suggéré ci-dessus mais plus puissant. Vous pouvez maintenant passer les deux paramètres (et plus) et avoir un arbre d'héritage plus compliqué. Finalement, ce que vous pouvez faire est de créer des propriétés privées (ou pseudo-privées, plus précises) en fournissant un getter à une variable autrement automatique (une passée en argument ou initilisée dans la fonction).Ceci est une caractéristique particulière de la langue et cela fonctionne comme ceci:

function BudgetType(type, spent) { 
    var instance = new BudgetItem(spent); 
    instance.getType = function() { 
     return type; 
    } 
    return instance; 
} 

Vous pouvez maintenant accéder au « type » passé dans le constructeur par obj.getType() mais ne peut pas remplacer la valeur initiale. Même si vous définissez obj.type = 'Nouvelle valeur', getType() retournera le paramètre initial passé car il contient une référence à un autre contexte qui a été créé lors de l'initialisation de l'objet et qui n'a jamais été libéré à cause de la fermeture.

espoir qui aide ...

+0

parfait! Merci – allouis

1

si vous voulez que tous les cas d'objets à référencer les mêmes membres/valeurs que vous pouvez utiliser une fermeture:

// create a constrctor for you object wrapped in a closure 
myCon = (function() { 

    // define shared members up here 
    var mySharedObj = new function() { 
     this.member = "a"; 
    }(); 

    // return the actual constructor 
    return function() { 
     this.mySharedObj = mySharedObj; 
    } 
}()); 

// create two instances of the object 
var a = new myCon(); 
var b = new myCon(); 


// Altering the shared object from one 
a.mySharedObj.member = "b"; 

// Alters it for all 
console.log(b.mySharedObj.member); 





Si vous voulez construire des objets à partir d'autres objets (sorte de comme les autres langues 'class whatever extends baseClass), mais ne veulent pas qu'ils partagent des valeurs par référence (à la place un clone de valeurs), vous pouvez utiliser quelque chose comme ce qui suit:

Object.prototype.extendsUpon = (function (_prop, _args) { 
    return function (base) { 
     for (var key in base) { 
      if (_prop.call(base, key)) { 
       this[key] = base[key]; 
      } 
     } 

     function con(child){ 
      this.constructor = child; 
     } 
     con.prototype = base.prototype; 

     this.prototype = new con(this); 
     this.__base__ = base.prototype; 

     var args = _args.call(arguments); 
     args.shift(); 
     base.constructor.apply(this, args); 
    } 
}(Object.prototype.hasOwnProperty, Array.prototype.slice)); 


ensuite pour construire des objets ontop d'objets:

// Base Object Constructor 
function Fruit(name) { 
    this.fruitname = name; 
} 
Fruit.prototype.yum = function() { 
    return "I had an " + this.fruitname; 
} 

// Object constructor that derives from the Base Object 
function Favorite() { 

    // Derive this object from a specified base object: 
    //  @arg0 -> Object Constructor to use as base 
    //  @arg1+ -> arguments passed to the BaseObject's constructor 
    this.extendsUpon(Fruit, "apple"); 

    // From here proceed as usual 

    // To access members from the base object that have been over-written, 
    // use "this.__base__.MEMBER.apply(this, arguments)" 
} 
Favorite.prototype.yum = function() { 
    return this.__base__.yum.apply(this) + " and it was my favorite"; 
} 
var mmm = new Favorite(); 

// Outputs: "I had an apple and it was my favorite" 
mmm.yum(); 
+0

C'est un peu déroutant pour moi mais je vais y travailler, mais c'est très instructif, j'apprécie votre temps, merci !! – allouis

Questions connexes