Qu'est-ce que var
réellement faire, et pourquoi ne met pas myObject = null
effectivement supprimer l'objet? Ces questions sont liées à un concept fondamental en matière de codage, qu'il s'agisse de la langue utilisée, AS3, JavaScript ou C #, et que vous pouvez le comprendre à l'aide de quelques éléments courants de la bibliothèque..
Commençons par les bases. Supposons que vous souhaitiez enregistrer l'âge de votre ami Bill:
var ageOfBill: Nombre = 24;
(Je vais utiliser AS3 pour cet exemple, mais les concepts de base sont les mêmes en JavaScript et C #.
En JavaScript, la syntaxe est presque la même, mais nous ne spécifions pas que l'âge est un nombre:
var ageOfBill = 24;
En C #, nous n'utilisons pas le var
mot-clé, mais nous spécifions le type de la variable:
ageOfBill court = 24;
Pas assez différent pour être déroutant, j'espère.)
Alors qu'est-ce qui se passe ici? Pense-y de cette façon:
var
(ou court
, en C #) signifie "obtenir un post-it frais".ageOfBill
signifie ", écrivez ageOfBill
en haut, au stylo ".= 24
signifie ", écrivez 24
sur la note, au crayon ".Et si plus tard on se rendait compte que Bill était en fait plus jeune que prévu?
var ageOfBill = 24; //… plus tard… ageOfBill = 20;
Cela signifie simplement que nous trouvons notre ageOfBill
note, effacer 24
, et écrire 20
à la place.
nous pourrait écrire var
encore:
var ageOfBill: Nombre = 24; //… plus tard… var ageOfBill: Number = 20;
… Mais ce n'est pas un bon code, car var
dit: "obtenez un post-it frais". Si vous faites cela, le compilateur comprendra généralement ce que vous voulez dire - c’est-à-dire que vous voulez changer ce qui est écrit sur le ageOfBill
Post-it note plutôt que d'en obtenir une nouvelle - mais il va probablement se plaindre.
Avertissement: # 3596: Définition de variable en double.
Cela dépend de la langue et de votre environnement de codage.
Pouvons-nous donc demander au compilateur d’obtenir un post-it frais et d’écrire une étiquette dessus au stylo, sans rien écrire au crayon? Peut-être pourrions-nous faire cela pour l'ami de Bill, Marty, dont nous ne connaissons pas l'âge:
var ageOfMarty: Nombre;
En fait (au moins en AS3), vous obtiendrez un nouveau post-it, écrivez ageOfMarty
au stylo, puis écrivez une valeur initiale par défaut de 0
là-bas au crayon:
Donc, en d'autres termes, nous ne pouvons pas avoir un post-it comme celui-ci sans prendre de la valeur.
D'accord, qu'en est-il si nous voulons conserver l'âge de Ted, le meilleur ami de Bill, qui a le même âge?
var ageOfTed: Number = ageOfBill;
Qu'est-ce qui se passe ici est, l'ordinateur regarde le ageOfBill
Post-it, puis copie le numéro inscrit au crayon sur un nouveau Post-it, sur lequel il écrit ageOfTed
en haut au stylo.
Ceci est juste une copie, cependant; si nous changeons alors la valeur de ageOfBill
ça n'affectera pas ageOfTed
:
ageOfBill = 21;
Alors! C'est très simple, et peut-être même intuitif. Parlons maintenant du premier point commun de douleur: les tableaux.
Pensez à un tableau comme un classeur.
(J'allais dire un Rolodex…
… Mais j'ai réalisé que je n'en avais jamais vu dans la vie réelle)
Chaque feuille à l'intérieur du classeur est semblable à l'une de ces notes Post-it, à l'exception du libellé stylo en haut. Au lieu de cela, nous nous référons à chaque feuille par le nom du classeur et le numéro de page de la feuille.
Supposons que nous ayons un groupe de tous nos amis, sans ordre particulier. Qui est sur la première page (page n ° 0)?
trace (amis [0]);
(trace()
écrit simplement la ligne dans la sortie de débogage; en JavaScript, vous pouvez utiliser console.log ()
et en C #, vous pouvez utiliser Console.WriteLine ()
dans le même but.)
C'est bill!
Alors, maintenant, que fait la ligne suivante?
var firstFriend: String = friends [0];
Il reçoit un nouveau Post-it (à cause de la var
mot-clé), écrit premier ami
au stylo, puis copie tout ce qui est écrit sur la première page du classeur sur cette note au crayon.
(Rappelles toi, Chaîne
signifie simplement un morceau de texte.)
Nous pouvons remplacer ce qui est écrit sur n’importe quelle page du classeur, comme avec les notes Post-it:
amis [0] = "Kyle";
… Et bien sûr cela n’affecte pas la premier ami
Post-it.
Le classeur est une analogie appropriée, car - comme avec un tableau - vous prenez des pages, en ajoutez de nouvelles et les réorganisez. Mais rappelez-vous, les pages individuelles agissent exactement comme les notes Post-it, sauf qu’elles n’ont pas leurs propres étiquettes de stylo, mais uniquement les numéros de page..
Toujours assez simple, j'espère. Alors, voici une question intéressante: que se passe-t-il quand vous faites ce qui suit?
var listOfNames: Array = friends;
Euh…
J'ai un peu triché ici, car j'ai beaucoup parlé de tableaux sans jamais expliquer comment nous en avons créé un. Alors abordons cela maintenant.
Supposons que vous tapez:
var friends: Array = ["Bill", "Marty", "Ted"];
… Ce qui se produit?
Comme d'habitude, var amis
signifie que nous obtenons un post-it frais et écrivons copains
en haut, au stylo:
Mais qu'est-ce qu'on écrit au crayon?
C'est une question piège: nous n'écrivons pas n'importe quoi.
Voir, Tableau
signifie "obtenir un nouveau classeur". Et ["Bill", "Marty", "Ted"]
signifie "mettre trois pages dans le classeur avec ces noms":
Et alors? C'est simple! Nous collons le copains
Post-it note sur la couverture du cartable:
Maintenant, quand nous écrivons:
trace (amis [0]);
… Nous savons que nous devons trouver le Post-it étiqueté copains
, puis regarde ce qui est écrit sur la première page (page 0) du classeur sur lequel il est collé.
En réalité, il existe très peu de types de variables dans lesquels une valeur est écrite au crayon sur une note Post-it. Dans AS3, les seuls types de ce type (appelés "primitives") sont:
Nombre
Chaîne
int
uint
Booléen
Pour tout le reste - Objet
, MovieClip
, XML
, et ainsi de suite - nous collons le post-it sur l'article lui-même.
(Les détails sont un peu différents en JavaScript et en C #, mais dans l’ensemble, la même idée s’applique.)
Revenons donc à notre question précédente. Quand on tape:
var listOfNames: Array = friends;
… ce qui se produit?
Encore une fois, nous savons que var listOfNames
signifie "obtenir un post-it frais et écrire listOfNames
en haut au stylo ". Et maintenant, nous savons que Tableau
signifie que nous collerons le post-it à quelque chose (un classeur), plutôt que d'écrire quelque chose sur le post-it au crayon.
Auparavant, lorsque nous faisions quelque chose de similaire, nous copions le contenu d’un post-it sur un autre. Donc, ici, devrions-nous obtenir un nouveau classeur et copier toutes les pages de la copains
liant dedans?
En fait non! Tout ce que nous faisons est de coller cette nouvelle listOfNames
Post-it note sur le même classeur que le copains
Un Post-it.
À présent, copains
et listOfNames
chacun se réfère à la exactement le même tableau. Donc si on écrit:
listOfNames [0] = "Emmett";
… puis amis [0]
volonté également être Emmett
, parce que listOfNames [0]
et amis [0]
reportez-vous à la même page dans le même classeur! Et comme cette page ne contient qu’une chaîne (qui est un type "primitif", n’oubliez pas), nous avons simplement effacé tout ce qui avait été écrit sur cette page et écrit Emmett
là au lieu.
nul
Signifier?Vu comme ça, nul
est assez facile à comprendre. Cette déclaration:
amis = null;
… Signifie simplement "enlever le copains
Post-it note de tout ce à quoi il est actuellement collé ".
le copains
Post-it encore existe, ce n'est que collé à rien. Donc si vous tapez:
trace (amis [0]);
ou
amis [0] = "Henry";
... alors vous obtiendrez une erreur, car vous essayez de référencer la première page du classeur que le copains
Post-it est collé à - mais ce n'est collé à rien!
Donc, pour être clair, la mise amis = null
n'affecte pas le liant du tout. Vous pouvez toujours y accéder très bien via listOfNames
. Et vous pouvez même taper:
amis = listOfNames;
… Pour revenir à l'ancienne situation:
Comme je l'ai dit, la mise amis = null
n'affecte pas directement le liant, mais il peut avoir une indirect effet.
Vous voyez, s'il n'y a aucune note Post-it collée sur le classeur, personne ne pourra plus jamais accéder au classeur. Ça va rester traîner, totalement inaccessible. Mais avoir tous ces classeurs (et autres objets) qui traînent, totalement abandonnés, est un réel gaspillage d'espace: ils encombrent la mémoire de l'ordinateur..
C'est là que le Éboueur entre. C'est un outil qui vérifie périodiquement la présence d'objets "perdus" et les jette à la poubelle - et une fois qu'ils sont partis, ils sont partis pour de bon; si un tableau est ramassé, toutes ses pages le sont aussi.
Dans la plupart des cas, cela ne vous affecte pas du tout. les objets ne sont récupérés que s'ils sont perdus et qu'ils ne peuvent pas être trouvés par votre code. Si vous en avez beaucoup, vous remarquerez peut-être un léger décalage de temps en temps lorsque le ramasse-miettes fait son travail (il faut un peu de temps pour ramasser activement les ordures). L'avantage est que cela libère plus d'espace (mémoire) pour votre application.
(Si vous souhaitez en savoir plus sur ce sujet, lisez les publications de Daniel Sidhion sur le ramassage des ordures et le regroupement d'objets.)
D'accord, il y a un autre grand concept à saisir - et c'est le plus complexe à ce jour.
Considérez cet extrait:
var firstFriendDetails: Array = ["Bill", 20]; var secondFriendDetails: Array = ["Marty", 16]; var thirdFriendDetails: Array = ["Ted", 20]; var allFriends: Array = [firstFriendDetails, secondFriendDetails, thirdFriendDetails];
Comment diable fait cette travail?
Commençons par ce que nous savons. Les trois premières lignes sont faciles. pour chacun nous:
En ce qui concerne cette ligne:
var allFriends: Array = [firstFriendDetails, secondFriendDetails, thirdFriendDetails];
… Nous allons avoir besoin de ficelle et de ruban adhésif.
Nous pouvons penser que cette ligne est équivalente à cet extrait:
var allFriends: Array = []; allFriends [0] = firstFriendDetails; allFriends [1] = secondFriendDetails; allFriends [2] = thirdFriendDetails;
La première ligne est facile: procurez-vous un nouveau classeur et un post-it, écrivez tous les amis
sur le post-it, et le coller au classeur.
Quant à la deuxième ligne:
allFriends [0] = firstFriendDetails;
Rappelez-vous que j'ai dit que chaque page d'un classeur est comme un post-it, sauf que rien n'est écrit au stylo. Si la première page était un post-it, nous la collerions tout simplement au début du firstFriendDetails
cartable à droite?
… Mais ça ne peut pas être à la fois sur le devant de ce cartable et à l'intérieur de l'autre classeur. Nous utilisons donc string:
Idem pour les deux autres:
Alors quand on veut savoir quoi tous les amis [2]
se réfère à, nous ouvrons simplement le tous les amis
classeur à cette page et suivez la chaîne - qui, bien sûr, conduit à la thirdFriendDetails
classeur.
De même, pour allFriends [1] [0]
, nous trouvons d'abord quel classeur tous les amis [1]
se réfère à, puis nous regardons la première page de cette liant… donc allFriends [1] [0]
est Marty
!
Maintenant, rassemblez toutes ces informations et gardez-les à l’esprit lors de la lecture de cet extrait:
var friends: Array = ["Bill", "Marty", "Ted", "Emmett", "Henry"]; var currentIndex: int = 0; var currentFriend: String; tandis que (currentIndex < 5) currentFriend = friends[currentIndex]; trace(currentFriend); var lastFriend:String = currentFriend; trace(lastFriend);
Et si on modifiait la valeur de currentFriend
dans la boucle?
var friends: Array = ["Bill", "Marty", "Ted", "Emmett", "Henry"]; var currentIndex: int = 0; var currentFriend: String; tandis que (currentIndex < 5) currentFriend = friends[currentIndex]; currentFriend = "Herbert"; trace(currentFriend); trace(friends[0]);
Que se passe-t-il si le tableau contient des objets non primitifs (MovieClips, images, tableaux, objets 3D, etc.)??
var friends: Array = [premier ami, deuxième ami, troisième ami, quatrième ami, cinquième ami]; var currentIndex: int = 0; var currentFriend: MovieClip; // ou ": Image" ou ": Objet" ou ": Tableau" ou autre chose (currentIndex < 5) currentFriend = friends[currentIndex]; currentFriend = sixthFriend; //What is the value of friends[0] now?
Enfin, que se passe-t-il si le tableau contient d’autres tableaux, qui contiennent eux-mêmes des primitives??
var firstFriendDetails: Array = ["Bill", 20]; var secondFriendDetails: Array = ["Marty", 16]; var thirdFriendDetails: Array = ["Ted", 20]; var quatriemeFriendDetails: Array = ["Emmett", 50]; var fifthFriendDetails: Array = ["Henry", 36]; var friends: Array = [firstFriendDetails, secondFriendDetails, thirdFriendDetails, 4thFriendDetails, fifthFriendDetails]; var currentIndex: int = 0; var currentFriend: Array; tandis que (currentIndex < 5) currentFriend = friends[currentIndex]; currentFriend[0] = "John"; currentFriend = ["Herbert", 29];
Que penses-tu de la valeur de amis [3] [0]
sera après?
Voici quelques autres remarques importantes que vous devriez connaître:
Dans AS3 et JavaScript, les objets ressemblent à des tableaux, sauf que chaque page est désignée par une étiquette plutôt que par son numéro de page. Pour que vous puissiez taper:
var detailsOfBill: Object = ; // "" signifie "créer un objet" detailsOfBill.title = "Esquire"; detailsOfBill.bandName = "Wyld Stallyns"; detailsOfBill.allNames = ["Bill", "S.", "Preston"];
… et c'est genre de comme obtenir un liant frais, coller un detailsOfBill
Postez-la au recto et remplissez-la de trois pages. La première page a l'étiquette Titre
écrit en haut au stylo et le mot Écuyer
écrit dessus au crayon; la deuxième page a l'étiquette Nom du groupe
dans un stylo et Wyld Stallyns
au crayon. La troisième page a l'étiquette allNames
mais n'a rien écrit au crayon; au lieu de cela, une chaîne l'attache à un autre classeur, dont les pages ne sont pas étiquetées: la première page dit: Facture
, le second dit S.
, et le troisième dit Preston
, tout au crayon.
(Pour rendre les choses encore plus confuses, les tableaux constituent techniquement une forme particulière d'Objet. Et si vous pensez que c'est mauvais, les fonctions peuvent également être considérées comme un type d'Objet! Mais c'est un sujet pour un futur article…)
J'ai dit que les objets sont ramassés s'il n'y a pas de post-it collé dessus, mais c'est une simplification excessive. Si une page d'un classeur pointe sur un objet via une chaîne (c'est-à-dire si myArray [0] = myObject
ou similaire), alors cet objet ne sera pas ramassé. Il en va de même si une page d'un classeur pointe vers un autre classeur (tableau) ou si la page d'un classeur d'objet pointe vers un autre classeur d'objet… et ainsi de suite. Cela s'applique même si le seul moyen d'accéder à l'objet consiste à utiliser un Post-it collé sur un classeur dont la page est liée à un autre classeur, aussi profond que vous le souhaitez..
Fondamentalement, le ramasse-miettes ne collecte un élément que s'il ne peut être atteint par aucune autre variable..
Cela explique pourquoi les objets affichés à l'écran ne peuvent généralement pas être collectés. En AS3, si un MovieClip ou un autre type DisplayObject figure dans la liste d'affichage, il est automatiquement ajouté à ce qui est essentiellement un tableau masqué d'objets d'affichage (auquel vous pouvez accéder via getChildAt ()). Des structures similaires existent en JavaScript et en C #. Ainsi, si un graphique est à l'écran et que vous supprimez toutes les références aux variables, aux tableaux et aux objets, il ne sera toujours pas nettoyé jusqu'à ce que vous le supprimiez de la liste d'affichage..
J'espère que cela aide à clarifier les choses. C'est certainement un concept déroutant lorsque vous le rencontrez pour la première fois: certaines variables contiennent en fait un valeur, tandis que d'autres ne contiennent qu'un référence à un objet. Ne vous inquiétez pas si vous n'êtes pas sûr à 100% de ce qui se passe exactement. ça fera plus de sens après un peu de pratique (et quelques erreurs!).
Toutefois, si vous avez des questions spécifiques à ce sujet, collez simplement un commentaire ci-dessous et je ferai de mon mieux pour vous répondre..
Merci d'avoir lu!