In JavaScript können Arrays mit dem Array -Konstruktor erstellt oder schnell mit [] erstellt werden, was auch die bevorzugte Methode ist. Das Array ist ein aus dem Objekt geerbter Prototyp, und es hat keinen speziellen Rückgabewert für TypeOF, es gibt nur 'Objekt' zurück.
In JS kann gesagt werden, dass alles ein Objekt ist und ein Array auch ein Array ist.
Viele Objekte haben viele bequeme Methoden wie Push, Concat, Slice usw. von Arrays. Wenn jedoch einige Objekte diese Methoden nicht implementieren, möchten wir diese Funktionen immer noch verwenden. Also, was soll ich tun?
1. Viele Methoden bieten sehr effiziente Implementierungen, und wir können ihre Implementierungen simulieren.
Beispielsweise unterstützen Browser unten IE8 die Array -Index -Methode nicht. Um den Array -Support -Indexof zu machen, können wir selbst eine Methode schreiben, um die Indexof -Methode zu implementieren:
(Drücken Sie F12, um mit dem IE -Browser zu debuggen, um die Browserversion zu IE5 auszuwählen.)
var arr = [,,,]; if (array.prototype.indexof) {alert ("Ihr Browser unterstützt die Index -Methode.");} else {alert ("Ihr Browser unterstützt keine Index -Methode.");} if (! array.Prototype.Indexof) {{array.prototype.prototy.Prototy.Prototy.ProToty.Protty.Prototype. i ++) {if (this [i] == item) {return i;}} return -;}} alert (arr.indexof ()); alert (arr.indexof ());Natürlich ist diese Methode sehr Müll. Ich werde in der spezifischen Implementierung hier nicht hässlich sein und eine Kopieversion auf Baidu anbieten:
Wenn Sie interessiert sind, können Sie sehen, wie die V8 -Engine implementiert wird: https://github.com/v8/v8/blob/master/src/js/array.js
if (! array.prototype.indexof) {array.prototype.indexof = function (ELT /*, von* /) {var len = this.Length >>>; var from = number (arguments []) || ; aus = (von <)? Math.ceil (aus): math.floor (von); if (von <) aus+= len; für (; aus <len; aus ++) {if (von in diesem && this [von] === elt) return von;} return -;};};};};};2. Vererbungsanruf und Anwenden von Methoden
Wenn wir ein Objekt haben, ist es dann nicht sehr problematisch, jedes Objekt zu schreiben, um es selbst zu implementieren?
In hochrangigen Sprachen können wir die Vererbung verwenden, um das Problem zu lösen, z. B. den folgenden Java-Code:
public class mylist <e> erweitert ArrayList <E> {public void myAdd (e) {Super.add (e); System.out.println ("add:"+e);}}Aber es gibt kein Konzept der Vererbung in JS. Wir können Anrufe verwenden und beantragen, um solche Probleme zu lösen.
Der obige Code kann als:
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();obj.add(,,);Hier können wir sehen: Obwohl die MyAdd-Methode in der Vererbungsmethode von Sprachen auf hoher Ebene implementiert ist, kann die MyAdd-Methode jetzt nur noch einen Parameter übergeben. Wenn Sie mehrere Parameter übergeben möchten, müssen Sie eine andere öffentliche Void MyAdd (E [] E) -Methode oder sogar die Methode für öffentliche void MyAdd (List <e> e) schreiben. JS kann mit einer Methode durchgeführt werden, wobei Argumente Objekt verwendet werden, um alle Parametereingaben darzustellen, was für hochrangige Sprachen schwierig ist.
(PS, in der Tat können Sie öffentliche Leere MyAdd (e ... e) in Java schreiben. Dies ist ein unsicherer Parameter. Die Verwendung von öffentlichem Leerraum MyAdd (e [] e) ist der gleiche)
Anruf- und Anwendenmethoden werden verwendet, um den Zeiger dieses Zeigers in der Funktion zu ändern. Call hat nur zwei Parameter, und anwenden werden normalerweise nach Kenntnis der Anzahl der Parameter verwendet. Das Folgende ist ein Beispiel:
var obj = function (name) {this.name = name;} obj.prototype.getName = function () {return this.name;} var obj1 = new obj ("zou"); var obj2 = {name: 'andy'};Die Referenz lautet:
anwenden (Objekt, arg1, arg2, ...)
Anruf (Objekt, [arg1, arg2, ......])
Es kann nur auf ein "Array" der Anruf einschließlich aller Parameter folgen. Auftragen ist ein syntaktischer Zucker. Wenn Sie die Anzahl der Parameter kennen, ist es sehr bequem, Anwendung zu verwenden.
Das obige Objekt kann auch null oder undefiniert sein, daher ist dieses Objekt globales Objekt (Fenster). Zum Beispiel wird das obige Beispiel befolgt:
var name = 'goo'; alert (obj1.getName.call (null)); (Im strengen Modus wird ein globales Objekt NULL ausgelöst: Unkundungssteuerung: Typeerror: Die Eigenschaft "Name" von NULL kann nicht lesen)
A. Object.DefineProperty
(Hinweis: Verwenden Sie diese Art von Funktionsart unter IE8 nicht)
Microsoft: Fügen Sie Objekten Eigenschaften hinzu oder ändern Sie die Eigenschaften vorhandener Eigenschaften.
Getters, Setzer,
Tatsächlich gibt es auch Getter und Setter -Funktionen für die Eigenschaften von Objekten in JS, aber ich persönlich denke, Getter und Setter in JS sind eher C#.
Beispielsweise definiert der folgende Code einen Getter/Setter:
Funktion myObj () {} Object.DefineProperty (myObj.prototype, 'Länge', {get: function () {return this.Length_; // Dies kann nicht Länge sein.}, set: function (value) {return this.Length_ = value;}});Der kommentierte Ort kann keine Länge sein, sonst ist er unendlich rekursiv.
Sie können die Länge auch schreibgeschützt entfernen und die Länge Variable vornehmen.
Object.DefineProperty (myObj.prototype, 'Länge', {get: function () {return this.length_; // Dies kann nicht Länge sein.}, /*Set: function (value) {return this.Length_ = value;}* /}); myobj.length = 3;Dieser Code macht eine Ausnahme: Uncornt TypeError: Die Eigenschaftslänge von #<Myobj> kann nicht festgelegt werden, die nur einen Getter hat.
Um die Eigenschaften des Objekts schreibgeschützt zu machen, können Sie auch beschreibbar verwenden: false.
Object.DefineProperty (MyObj.Prototype, 'Länge', {Schreibbar: False});Beschreibbar: Falsch kann nicht mit GET -Set koexistieren, andernfalls wird ein Typfehler geworfen.
Konfigurierbar: Kann es mit Löschanweisung gelöscht werden, aber die konfigurierbare Eigenschaft scheint im strengen Modus gültig zu sein. Ein solcher Code kann weiterhin im Nichtstreifenmodus ausgeführt werden: (gemeldet ein Fehler im strengen Modus)
Object.DefineProperty (myObj.prototype, 'Länge', {konfigurierbar: false}); var obj = new MyObj (); löschen obj.length;Wert: Gibt den festen Wert des Objekts an. Wert: 10, was angibt, dass der Anfangswert dieses Objekts 10 beträgt.
Im Nicht-Streng-Modus meldet ein solcher Code keinen Fehler, und im strengen Modus meldet er einen Fehler:
Object.DefineProperty (MyObj.Prototype, 'Länge', {schriftlich: false, value: '10 '}); var obj = new MyObj (); obj.length = 100;Sie können GetownPropertyDescriptor verwenden, um diese Werte zu erhalten und zu ändern. Zum Beispiel ist meine Länge Eigenschaft schreibgeschützt.
Ausführen eines solchen Codes, aber ein Fehler ist aufgetreten:
Object.DefineProperty (MyObj.Prototype, 'Länge', {value:, schriftlich: false,}); var Descriptor = Object.getownPropertyDescriptor (myobj.Prototype, "Länge"); Descriptor.Writable; Unbefundt TypeRror: Die Eigenschaft kann nicht neu definieren: LängeDies liegt daran, dass der Standardwert von Konfigurierbar falsch ist. Nach dem Aufrufen von DefineProperty hat Configurable die falsche Eigenschaft, sodass sie nicht umgekehrt werden kann. Es kann in Zukunft nicht verändert werden.
Daher müssen Sie konfigurierbar: true verwenden, und diese Objekteigenschaft kann geändert werden. Der vollständige Code lautet wie folgt:
Object.DefineProperty (MyObj.Prototype, 'Länge', {value:, schriftlich: false, konfigurierbar: true}); var Descriptor = Object.getownPropertyDescriptor (myobj.prototype, "Länge"); Descriptor.writable = true; dojec.DefineProperty (myobj.protype, Deskriptor); =; var obj = new myobj (); alert (obj.length);Sie können einen Satzdeskriptor hinzufügen. Konfigurierbar = false;
Dies bedeutet, dass ich diese Eigenschaft geändert habe, und Sie können sie in Zukunft nicht ändern
Diese Funktion ist auch in vielen Fällen nützlich. Wenn Sie Anrufe verwenden und Methoden anwenden, muss die Länge des Objekts variabel sein. Wenn das Längenattribut des Objekts nur schreibgeschützt ist, wird eine Ausnahme beim Anruf aufrufen und angewendet.
Beispielsweise kann die Länge des DomTokenList -Objekts nicht geändert werden. Ich habe eine DOM -Objekt -DomToken -Liste,
Es ist jedoch konfigurierbar. Wir können es so ändern, dass die Länge Eigenschaft geändert werden kann:
Siehe, dieser Konfigurierbare ist wahr und der Setter ist undefiniert. Schreiben wir eine festgelegte Methode dafür, nicht in Ordnung?
var Descriptor = Object.getownPropertyDescriptor (DomTokenList.Prototype, 'Länge'); Descriptor.set = Funktion (value) {this.Length = value;} Objekt.DefineProperty (DomTokenList.Prototype, 'Länge', Deskriptor);Dann rennen,
Eine weitere Ausnahme wurde geworfen, ein ungekundetes RangelEror: Maximale Call -Stapelgröße überschritten (…)
Dies liegt daran, dass wenn wir diese Länge festlegen, es in dieser von uns geschriebenen Methode unendlich wieder auftritt.
Daher müssen wir Delete verwenden, um den Einfluss des Längenattributs zu beseitigen, dh:
var Descriptor = Object.getownPropertyDescriptor (DomTokenList.Prototyp, 'Länge'); Descriptor.set = Funktion (value) {delete domTokenList.Prototype.length; this.Length = value;} Object.DefineProperty (DomTokenList.Prototype, 'Länge', Deskriptor);Auf diese Weise unterstützt DomTokenList auch Push, Pop und andere Operationen.
Array.prototype.push.call (document.body.classlist, 'ABC')
Dann einkapseln
DomTokenList.Prototype.push = function () {array.prototype.push.call (document.body.classlist, array.prototype.slice.call (Argumente));};};Die Methode Array.Prototype.Slice.Call (Argumente) wird verwendet, um Argumenteobjekte in Arrays umzuwandeln.