Dans JavaScript, les tableaux peuvent être créés à l'aide du constructeur du tableau, ou rapidement créés à l'aide de [], qui est également la méthode préférée. Le tableau est un prototype hérité de l'objet, et il n'a pas de valeur de retour spéciale pour le typeof, il renvoie uniquement «objet».
Dans JS, on peut dire que tout est un objet, et un tableau est également un tableau.
De nombreux objets ont de nombreuses méthodes pratiques telles que Push, Concat, Slice, etc. des tableaux, mais si certains objets n'implémentent pas ces méthodes, nous voulons toujours utiliser ces fonctions. Alors que dois-je faire?
1. De nombreuses méthodes fournissent des implémentations très efficaces et nous pouvons simuler leurs implémentations.
Par exemple, les navigateurs ci-dessous IE8 ne prennent pas en charge la méthode d'index de tableau. Afin de faire de l'index de support du tableau, nous pouvons écrire une méthode nous-mêmes pour implémenter l'index de la méthode:
(Appuyez sur F12 pour déboguer avec IE Browser pour sélectionner la version du navigateur à IE5.)
var arr = [, ,,]; if (array.prototype.indexof) {alert ("Votre navigateur prend en charge l'index de la méthode.");} else {alert ("Votre navigateur ne prend pas en charge l'index de la méthode.");} if (! array.prototype.indexof) {array.prototype.indexof = fonction (élément) {pour (var i =; i ++) {if (this [i] == item) {return i;}} return -;}} alert (arr.indexof ()); alert (arr.indexof ());Bien sûr, cette méthode est très déchet. Je ne serai pas moche dans l'implémentation spécifique ici et fournira une version de copie sur Baidu:
Si vous êtes intéressé, vous pouvez voir comment le moteur V8 est implémenté: https://github.com/v8/v8/blob/master/src/js/array.js
if (! array.prototype.indexof) {array.prototype.indexof = fonction (elt / *, from * /) {var len = this.length >>>; var from = nombre (arguments []) || de = (de <)? Math.ceil (de): math.floor (from); if (from <) from + = len; for (; from <len; from ++) {if (from in this && this [from] === elt) return de;} return -;};};2. Héritage d'appel et appliquer des méthodes
Si nous avons un objet, n'est-il pas très difficile d'écrire chaque objet pour le mettre en œuvre vous-même?
Dans les langues de haut niveau, nous pouvons utiliser l'héritage pour résoudre le problème, comme le code Java suivant:
La classe publique MyList <e> étend ArrayList <e> {public void myAdd (e e) {super.add (e); System.out.println ("add:" + e);}}Mais il n'y a pas de concept d'hérédité dans JS. Nous pouvons utiliser l'appel et postuler pour résoudre ces problèmes.
Le code ci-dessus peut être réécrit comme:
var myObject = function () {} myObject.prototype.add = function () {array.prototype.push.call (this, arguments); // output argumentsfor (var i =; i <arguments.length; i ++) {console.log ("add:" + arguments [i]);}} var obj = new MyObject ();Ici, nous pouvons voir: bien que la méthode MYADD soit implémentée dans la méthode d'héritage des langages de haut niveau, la méthode MyAdd ne peut passer qu'un seul paramètre maintenant. Si vous souhaitez transmettre plusieurs paramètres, vous devez écrire une autre méthode publique MyAdd (e [] e), ou même la méthode publique MyAdd (List <e> E). JS peut être effectué avec une méthode, en utilisant l'objet Arguments pour représenter toutes les entrées de paramètres, ce qui est difficile à faire pour les langages de haut niveau.
(PS, en fait, vous pouvez écrire le public public MyAdd (e ... e) en Java. Il s'agit d'un paramètre incertain. L'utilisation du vide public MyAdd (e [] e) est la même))
Les méthodes d'appel et d'application sont utilisées pour modifier le pointeur de ce pointeur dans la fonction. L'appel n'a que deux paramètres et l'application est généralement utilisée après avoir connu le nombre de paramètres. Ce qui suit est un exemple:
var obj = fonction (name) {this.name = name;} obj.prototype.getName = function () {return this.name;} var obj1 = new obj ("zou"); var obj2 = {name: 'Andy'}; var name = obj1.getName.call (obj2); alert (nom);La référence est:
Appliquer (Object, Arg1, Arg2, ...)
Appelez (Object, [Arg1, Arg2, ......])
Un seul "tableau" peut être suivi de l'appel, y compris tous les paramètres. Appliquer est un sucre syntaxique. Si vous connaissez le nombre de paramètres, il sera très pratique de l'utiliser.
L'objet ci-dessus peut également être nul ou non défini, donc cet objet est un objet global (fenêtre). Par exemple, l'exemple ci-dessus sera suivi:
var name = 'goo'; alert (obj1.getName.call (null)); (En mode strict, puisque l'objet global est nul, une exception sera lancée: non apparenté: Impossible de lire la propriété «Nom» de Null)
3. Object.DefineProperty
(Remarque: n'utilisez pas ce type de fonctionnalité ci-dessous IE8)
Microsoft: ajouter des propriétés aux objets ou modifier les propriétés des propriétés existantes.
Getters, setters,
En fait, il y a aussi des fonctions Getters et Setter pour les propriétés des objets dans JS, mais je pense personnellement que les getters et les setters en js ressemblent plus à C #.
Par exemple, le code suivant définit un Getter / Setter:
fonction myoBj () {} object.defineproperty (myobj.prototype, 'longueur', {get: function () {return this.length_; // Cela ne peut pas être la longueur.}, set: function (value) {return this.length_ = value;}});L'endroit commenté ne peut pas être longue, sinon il sera infiniment récursif.
Vous pouvez également supprimer le jeu et créer la variable de longueur en lecture seule.
Object.defineProperty (myoBj.prototype, 'longueur', {get: function () {return this.length_; // Cela ne peut pas être la longueur.}, / * Set: function (value) {return this.length_ = value;} * /}); myoBj.length = 3;Ce code lancera une exception: non apparente TypeError: Impossible de définir la longueur de la propriété de # <MyObj> qui n'a qu'un getteur.
Pour rendre les propriétés de l'objet en lecture seule, vous pouvez également utiliser Writables: False.
Object.defineProperty (myobj.prototype, 'longueur', {writeable: false});Writable: False ne peut pas coexister avec Get Set, sinon une erreur de type sera lancée.
Configurable: peut-il être supprimé avec une instruction de suppression, mais la propriété configurable semble être valide en mode strict. Un tel code peut encore être exécuté en mode non stricte: (signalé une erreur en mode strict)
Object.defineProperty (myObj.prototype, 'longueur', {configurable: false}); var obj = new myoBj (); delete obj.length;Valeur: spécifie la valeur fixe de l'objet. Valeur: 10, indiquant que la valeur initiale de cet objet est 10.
En mode non stricte, un tel code ne rapportera pas d'erreur et en mode strict, il rapportera une erreur:
Object.defineProperty (myobj.prototype, 'longueur', {withing: false, value: '10 '}); var obj = new myoBj (); obj.length = 100;Vous pouvez utiliser GOSOWNPROPERTYDScriptor pour obtenir et modifier ces valeurs. Par exemple, maintenant ma propriété de longueur est en lecture seule.
Exécuter un tel code, mais une erreur s'est produite:
Object.defineproperty (myobj.prototype, 'longueur', {value :, withing: false,}); var descriptor = object.getownpropertyDescriptor (myoBj.prototype, "longueur"); descriptor.writable = true; object.defineproperty (myoBj.prototype, 'Length', Descriptor); Typeau PRINCED: Impossible de redéfinir la propriété: LongueurEn effet, la valeur par défaut de configurable est fausse. Après avoir appelé DefineProperty, Configurable a la fausse propriété, il ne peut donc pas être inversé. Il ne peut pas être modifié à l'avenir.
Par conséquent, vous devez utiliser configurable: true, et cette propriété d'objet peut être modifiée. Le code complet est le suivant:
Object.defineproperty (myobj.prototype, 'longueur', {value :, withing: false, configurable: true}); var descriptor = object.getownpropertydescriptor (myobj.prototype, "longueur"); descriptor.witable = true; objet.defineproperty (myobj.pototype, 'longueur', descriptor); Myobj.pototypet =; var obj = new myoBj (); alert (obj.length);Vous pouvez ajouter une phrase Descriptor.Configurable = false;
Cela signifie que j'ai modifié cette propriété et que vous ne pouvez pas le modifier à l'avenir
Cette fonctionnalité est également utile dans de nombreux cas. Si vous utilisez des méthodes d'appel et d'application, la longueur de l'objet doit être variable. Si l'attribut de longueur de l'objet est en lecture seule, une exception sera lancée lors de l'appel d'appel et de l'application.
Par exemple, la longueur de l'objet DomtokenList ne peut pas être modifiée. J'ai un objet Dom Domtokenlist,
Mais son configurable est vrai, nous pouvons le modifier afin que sa propriété de longueur puisse être modifiée:
Voir, ce configurable est vrai et le secteur n'est pas défini. Écrivons une méthode de jeu pour cela, n'est-ce pas?
var descriptor = object.getownpropertyDescriptor (domtokenList.prototype, 'longueur'); descriptor.set = function (value) {this.length = value;} object.defineproperty (domtokenList.prototype, 'longueur', descriptor);Puis courez,
Une autre exception a été lancée, non apparenté RangeError: la taille maximale de la pile d'appels dépassée (…)
En effet, lorsque nous définissons ceci.Length, il se reproduira infiniment dans cette méthode d'ensemble que nous écrivons.
Par conséquent, nous devons utiliser la suppression pour éliminer l'influence de l'attribut de longueur, c'est-à-dire:
var descriptor = object.getownpropertyDescriptor (domtokenList.prototype, 'longueur'); descriptor.set = function (value) {delete domtokenList.prototype.length; this.length = value;} object.defineproperty (domtokenList.prototype, «longueur», descripteur);De cette façon, DomtokenList prend également en charge les opérations push, pop et autres.
Array.prototype.push.call (document.body.classlist, 'ABC')
Puis encapsuler
DomtokenList.prototype.push = function () {array.prototype.push.call (document.body.classlist, array.prototype.slice.call (arguments));}La méthode array.prototype.slice.call (arguments) est utilisée pour convertir les objets d'arguments en tableaux.