Javascript Prototypes, objets, constructeur? Je suis confus

J'ai traversé beaucoup de questions de Stack Overflow qui avaient une description, mais je les ai vraiment trouvées très déroutantes. Ce que je veux, c'est une explication simple, ne renvoyez pas un lien.

Je suis totalement confus, complètement confiné entre:

J'ai fait beaucoup de recherches, mais je les ai trouvés très compliqués.

Toute explication simple?

Tu es chanceux. Il y a une explication très simple:

Première étape: Créer un objet

Dites que vous voulez encercler:

var circle = {}; 

Deuxième étape: Donnez-lui certaines propriétés

Un cercle peut être dessiné, alors, créez une propriété appelée draw :

 circle.draw = function () { // drawing logic }; 
  1. Une propriété est simplement une variable appartenant à un objet. Une variable par elle-même n'est pas une propriété.
  2. Les propriétés et les variables peuvent contenir tout type de données. Les fonctions en JavaScript sont des données.
  3. Lorsqu'une propriété détient une fonction, elle s'appelle une méthode.

Par conséquent, nous avons une méthode appelée draw appartenant au circle objet.

Troisième étape: étendre un objet

Maintenant, je veux une balle et une balle est comme un cercle. Alors, étendons le circle pour créer une balle:

 var ball = Object.create(circle); 
  1. Ici, nous avons pris le circle l'objet et l'avons utilisé pour créer un nouvel objet appelé ball .
  2. La ball objet a maintenant toutes les propriétés du circle . Nous pouvons donc appeler ball.draw .
  3. Le circle objet est le prototype de ball .

Quatrième étape: Donnez-lui certaines propriétés

Chaque balle a un radius , alors donnons la nôtre:

 ball.radius = 5; 

Cinquième étape: créer un constructeur

Il y a un problème ici. Chaque fois que je veux créer une nouvelle balle, circle et définis manuellement le radius de la balle. Au lieu de cela, je voudrais une fonction pour créer le ballon et me donner un rayon pour moi. Cette fonction s'appelle un constructeur:

 function createBall(radius) { var ball = Object.create(circle); ball.radius = radius; return ball; } var baseball = createBall(5); var basketball = createBall(10); baseball.draw(); basketball.draw(); 

C'est à peu près tout ce que vous devez savoir sur les prototypes, les objets et les constructeurs.

Bien sûr, il y a beaucoup d'explications, mais c'est trop pour une réponse StackOverflow. J'ai écrit une publication sur le blog, et je n'ai pas l'intention de réécrire la même chose ici. Vous devriez lire mon blog. Cela en vaut la peine: http://aaditmshah.github.io/why-prototypal-herheritance-matters


Edit: Bien sûr, je vais expliquer ce qui se passe dans ce code: http://cssdeck.com/labs/4ksohwya

Tout d'abord, faites défiler jusqu'à la fin:

 window.addEventListener( 'load', init(null), false); 

Lorsque la page la charge, elle exécute init :

 function init(images) { canvas= document.getElementById('s'); ctx= canvas.getContext('2d'); canvas.width= window.innerWidth; canvas.height=window.innerHeight; garden= new Garden(); garden.initialize(canvas.width, canvas.height, 300); lerp(0,2000); time= new Date().getTime(); interval = setInterval(_doit, 30); } 

La fonction init crée une instance de Garden ( garden = new Garden(); ) et exécute la méthode d' initialize du garden . Il appelle également la fonction _doit en intervalles de 30 millisecondes.

 initialize : function(width, height, size) { this.width= width; this.height= height; this.grass= []; for(var i=0; i<size; i++ ) { var g= new Grass(); g.initialize( width, height, 50, // min grass height height*2/3, // max grass height 20, // grass max initial random angle 40 // max random angle for animation ); this.grass.push(g); } this.stars= []; for( i=0; i<this.num_stars; i++ ) { this.stars.push( Math.floor( Math.random()*(width-10)+5 ) ); this.stars.push( Math.floor( Math.random()*(height-10)+5 ) ); } }, 

La méthode d' initialize du garden crée alors certaines instances de Grass , appelle leurs méthodes d' initialize et les stocke dans un tableau.

 function _doit() { ctx.fillStyle= gradient; ctx.fillRect(0,0,canvas.width,canvas.height); var ntime= new Date().getTime(); var elapsed= ntime-time; garden.paint( ctx, elapsed ); // lerp. if ( elapsed>nextLerpTime ) { lerpindex= Math.floor((elapsed-nextLerpTime)/nextLerpTime); if ( (elapsed-nextLerpTime)%nextLerpTime<lerpTime ) { lerp( (elapsed-nextLerpTime)%nextLerpTime, lerpTime ); } } } 

La fonction _doit appelle la fonction de paint du garden , et la fonction de paint du garden appelle la fonction de paint de chaque herbe.


Donc, il y a deux constructeurs:

  1. Grass
  2. Garden

Voici les deux prototypes:

  1. Grass.prototype
  2. Garden.prototype

A l'intérieur de la fonction init , nous créons une instance unique de Garden (c'est un objet):

 var garden= new Garden(); 

À l'intérieur de la méthode d' initialize du garden nous créons plusieurs instances de Grass :

 var g= new Grass(); 

C'est tout.

D'accord, une tournée tourbillonnaire:

Objets

Un objet est une chose qui possède des propriétés . Les propriétés ont des noms et des valeurs. Les noms sont toujours des chaînes (bien que nous puissions les écrire sans quotes la plupart du temps), et les valeurs peuvent être tout ce que le JavaScript supporte: nombres, chaînes, booleans, null, indéfinis ou références aux objets.

Alors:

 var a = { propertyName: "property value" }; 

a est une variable se référant à un objet, qui a une propriété nommée propertyName , dont la valeur est la chaîne "property value" .

Prototypes

Un objet (par exemple, obj ) peut avoir un autre objet (disons, p ) "derrière", où p prête ses propriétés à moins que obj n'ait sa propre propriété avec un prénom. p est le prototype objet d' obj . C'est le plus simple à comprendre avec un exemple:

 // Let's create an object `p` with a couple of properties, `x` and `y` // This syntax is called an "object initializer" (aka "object literal") var p = { x: "x on p", y: "y on p" }; // Now, we'll create a new object, `obj`, using `p` as its prototype var obj = Object.create(p); // And that means if we ask `obj` for a property called `x`, since it doesn't // have its **own** `x`, it asks `p` for it. (And the same with `y`) console.log(obj.x); // "x on p" console.log(obj.y); // "y on p" // But we can give `obj` its *own* `x` instead if we want obj.x = "x on obj"; console.log(obj.x); // "x on obj" console.log(obj.y); // "y on p" // Doing that to `obj` had no effect on `p` console.log(px); // "x on p" console.log(py); // "y on p" 

Un aspect très important des prototypes est que la connexion entre les objets est en direct . Donc, si obj n'a pas de propriété y , chaque fois que nous demandons obj pour y va et demande p . Donc, si nous changeons la valeur de p pour y , ce changement apparaît si nous demandons à obj pour cela:

 var p = { x: "x on p", y: "y on p" }; var obj = Object.create(p); console.log(obj.y); // "y on p" py = "updated y on p"; console.log(obj.y); // "updated y on p" 

Cette connexion en direct est une chose essentielle. Encore une fois, pensez-y comme ceci: Nous demandons à obj pour la propriété y , et obj dit: "Je n'ai pas le mien, alors je vais demander à faire pour et vous donner".

Remarque: La fonction Object.create que j'ai utilisée pour créer obj est nouvelle comme ECMAScript5 (la mise à jour des spécifications depuis quelques années). Nous reviendrons sur une autre façon de donner à un objet un prototype plus bas.

Le prototype d'un objet est actuellement toujours défini lorsque l'objet est créé et ne peut pas être modifié (je ne pourrais pas échanger un q au lieu de p ci-dessus après la création d' obj ). Au-dessus, j'utilise Object.create pour le faire (et ci-dessous nous parlerons des fonctions du constructeur). Jusqu'à ECMAScript5 (ES5), il n'y avait aucun moyen standard d'obtenir le prototype d'un objet. ES5 nous donne un moyen de le faire maintenant, appelé Object.getPrototypeOf , mais n'offre pas encore un moyen de le modifier. La prochaine version, ES6, prendra les choses un peu plus loin.

Les fonctions

Les fonctions sont des unités de code qui font les choses. Les fonctions sont également des objets, et donc ils peuvent avoir des propriétés, bien qu'en pratique, il est relativement rare d'utiliser des propriétés sur les fonctions (autres que les call et les apply , dont nous n'avons pas besoin de parler ici).

Vous pouvez déclarer une fonction:

 function foo() { } 

… ou vous pouvez en créer un avec une expression :

 // An anonymous -- unnamed -- function assigned to variable `foo` var foo = function() { }; // A function named `f` assigned to variable `foo` var foo = function f() { }; 

Les déclarations et les expressions sont différentes. Les déclarations de fonctions sont évaluées avant qu'un code étape par étape dans la même portée ne soit effectué. Les expressions de fonctions sont évaluées lorsqu'elles sont rencontrées dans le code étape par étape, comme toutes les autres expressions. (Les gens appellent parfois ce "levage" car cela signifie qu'en effet, même si une déclaration de fonction est au bas d'une portée, cela se produit comme s'il avait été levé – hissé – vers le haut.)

Les fonctions peuvent avoir des arguments:

 // `a` and `b` are arguments function sum(a, b) { console.log(a + b); } 

Et ils peuvent avoir des valeurs de retour:

 function sum(a, b) { return a + b; } console.log(sum(1, 2)); // "3" 

Si une fonction ne renvoie pas autre chose, le résultat de l'appel de la fonction est la valeur undefined .

Méthodes

JavaScript n'a pas de méthodes. Il a seulement des fonctions, mais c'est tout ce dont il a vraiment besoin. Mais si vous avez une fonction assignée à une propriété d'objet et que vous appelez cette fonction dans le cadre d'une expression qui récupère la propriété de l'objet, il se produit quelque chose qui fait que JavaScript semble avoir des méthodes: le mot this clé se réfère à cet objet dans la fonction appel. Encore une fois, un exemple fait des miracles:

 // A blank object var obj = {}; // Lets put a function on it as a property obj.foo = function() { console.log("this is obj? " + this === obj); }; // Let's call that function obj.foo(); // "this is obj? true" 

Plus sur mon blog:

  • Méthodes mythiques
  • Vous devez vous en souvenir

Constructeurs

Les fonctions de constructeur sont utilisées avec le new mot-clé, et elles constituent l'une des façons dont vous donnez un objet à un prototype. Lorsque vous appelez une fonction via un new , un nouvel objet est créé et a attribué un prototype à partir de la propriété prototype de la fonction:

 function Foo() { } Foo.prototype.x = "x on Foo.prototype"; var obj = new Foo(); console.log(obj.x); // "x on Foo.prototype" 

Chaque fonction possède automatiquement un prototype propriété, même si, bien sûr, nous n'utilisons pas la grande majorité des fonctions de constructeurs.

Une chose importante à noter ici: la propriété prototype d'une fonction n'est qu'une ancienne propriété ennuyeuse. Ce n'est pas le prototype d'un objet jusqu'à ce que, à moins que cette fonction ne soit appelée via le new opérateur. Le new opérateur utilise la propriété prototype de la fonction pour configurer le prototype du nouvel objet lorsque vous appelez la fonction par une new , mais c'est tout.

Il convient de mentionner que jusqu'à ES5, les fonctions du constructeur comme ci-dessus étaient la seule façon de créer un objet avec un prototype donné. Mais avec ES5, nous avons obtenu Object.create , qui a ouvert plus de modèles pour utiliser JavaScript. (Il a toujours été possible de créer votre propre Object.create , en utilisant une fonction temporaire, et en fait, c'est exactement ce que certains ont fait.) Certaines personnes n'aiment pas utiliser le new mot-clé et la propriété prototype , ils préfèrent utiliser un Modèle "générateur" où vous appelez simplement une fonction et récupérez un objet. JavaScript est tellement flexible que vous pouvez le faire.


Plus à Explorer

  • J'écris sur JavaScript sur mon blog: Nifty Snippets – javascript label

  • Le Mozilla Development Network dispose d'excellentes informations JavaScript.

  • Il y a, bien sûr, la spécification – c'est la meilleure source pour le détail réel, mais c'est très difficile à lire 🙂

Je suppose que je suis trop tard, mais ce serait mes 2 cents:

Prototype:

 String.prototype.x = "yahoo" 

Maintenant chaque instance de String aura la propriété x .

Donc, ce soit (new String()).x ou "".x ont tous deux la valeur égale à yahoo

Par conséquent, c'est comme étendre une classe prédéfinie.


Objets

Tout en JavaScript, à l'exception des autres types primitifs, est un objet.

Un objet est une collection de paires nom-valeur, rien de plus, rien de moins.

 {"a": 0, "b" : 1} 

Même un Array est un objet dans JS avec des propriétés et des méthodes supplémentaires.


Fonctions et méthodes

Voici une fonction:

 function a() { }; 

Maintenant, donnons le statut d'une méthode d'un tableau :

 Array.prototype.a = a; 

Constructeur:

 new String() 

String.constructor la mise en œuvre de String à partir de: String.constructor

De même, le code que vous écrivez dans une fonction va dans cette même fonction.

JavaScript est le langage de script utilisé dans les applications Web pour rendre les pages Web dynamiques. Cette langue permet de gérer les actions de l'utilisateur en traitant les événements sur les éléments affichés sur la page …. Elle sert également à modifier le contenu de la page Web en fonction de la condition …

La fonction méthode (ou) est la construction de programmation utilisée dans javascript pour spécifier la logique. Vous mettez la logique requise dans une méthode et vous l'invoquerez à partir de la page Web lors d'un événement …

Il n'y a aucun constructeur en javascript …

Il y aura des objets implicites et définis par l'utilisateur dans javascript … Les objets implicites incluent Date, Array etc …

Ceci est juste un résumé de base … vous devez suivre les sites Web (ou) pour en savoir plus sur javascript