// Underscore.js 1.3.3
// (c) 2009–2012 Jeremy Ashkenas, DocumentCloud Inc.
// Underscore ist unter der MIT-Lizenz frei vertreibbar.
// Teile von Underscore sind von Prototype inspiriert oder entlehnt,
// Oliver Steeles Functional und John Resigs Micro-Templating.
// Für alle Details und Dokumentation:
// http://documentcloud.github.com/underscore
(Funktion() {
// Erstelle ein globales Objekt, dargestellt als Fensterobjekt im Browser und als globales Objekt in Node.js
var root = this;
//Speichern Sie den Wert, bevor „_“ (Unterstrichvariable) überschrieben wird
// Wenn ein Namenskonflikt vorliegt oder die Spezifikation berücksichtigt wird, kann die Methode _.noConflict() verwendet werden, um den Wert von „_“ wiederherzustellen, bevor er von Underscore belegt wurde, und das Underscore-Objekt zum Umbenennen zurückzugeben
var previousUnderscore = root._;
//Erstelle eine leere Objektkonstante für die interne Freigabe und Verwendung
var breaker = {};
//Zwischenspeichern Sie die Prototypenkette des integrierten Objekts in einer lokalen Variablen, um einen schnellen Aufruf zu ermöglichen
var ArrayProto = Array.prototype, //
ObjProto = Object.prototype, //
FuncProto = Function.prototype;
//Häufige Methoden in integrierten Objektprototypen in lokalen Variablen zwischenspeichern, um sie schnell aufrufen zu können
var Slice = ArrayProto.slice, //
unshift = ArrayProto.unshift, //
toString = ObjProto.toString, //
hasOwnProperty = ObjProto.hasOwnProperty;
// Dies definiert einige neue Methoden, die von JavaScript 1.6 bereitgestellt werden
// Wenn die Host-Umgebung diese Methoden unterstützt, werden sie zuerst aufgerufen. Wenn die Host-Umgebung sie nicht bereitstellt, werden sie von Underscore implementiert.
var nativeForEach = ArrayProto.forEach, //
nativeMap = ArrayProto.map, //
nativeReduce = ArrayProto.reduce, //
nativeReduceRight = ArrayProto.reduceRight, //
nativeFilter = ArrayProto.filter, //
nativeEvery = ArrayProto.every, //
nativeSome = ArrayProto.some, //
nativeIndexOf = ArrayProto.indexOf, //
nativeLastIndexOf = ArrayProto.lastIndexOf, //
nativeIsArray = Array.isArray, //
nativeKeys = Object.keys, //
nativeBind = FuncProto.bind;
// Erstellen Sie eine Aufrufmethode im Objektstil, die einen Underscore-Wrapper zurückgibt. Der Prototyp des Wrapper-Objekts enthält alle Methoden von Underscore (ähnlich dem Einschließen eines DOM-Objekts in ein jQuery-Objekt).
var _ = Funktion(obj) {
// Alle Underscore-Objekte werden intern durch Wrapper-Objekte erstellt
neuen Wrapper(obj) zurückgeben;
};
// Speichern Sie für verschiedene Hostumgebungen die benannten Variablen von Undersocre in verschiedenen Objekten.
if( typeof exports !== 'undefiniert') {// Node.js-Umgebung
if( typeof module !== 'undefiniert' && module.exports) {
exports = module.exports = _;
}
exporte._ = _;
} else {//Die benannte Variable von Underscore in der Browserumgebung wird im Fensterobjekt aufgehängt
root['_'] = _;
}
// Versionsanweisung
_.VERSION = '1.3.3';
// Sammlungsbezogene Methoden (allgemeine Verarbeitungsmethoden für Daten und Objekte)
//--------------------
// Den Prozessor iterieren und die Prozessormethode für jedes Element in der Sammlung ausführen
var every = _.each = _.forEach = function(obj, iterator, context) {
//Keine Nullwerte verarbeiten
if(obj == null)
zurückkehren;
if(nativeForEach && obj.forEach === nativeForEach) {
// Wenn die Hostumgebung dies unterstützt, wird zuerst die von JavaScript 1.6 bereitgestellte forEach-Methode aufgerufen.
obj.forEach(iterator, context);
} else if(obj.length === obj.length) {
//Führen Sie die Prozessormethode für jedes Element im <array> aus.
for(var i = 0, l = obj.length; i < l; i ) {
if( i in obj && iterator.call(context, obj[i], i, obj) === breaker)
zurückkehren;
}
} anders {
// Die Prozessormethode für jedes Element in <object> ausführen.
for(var-Schlüssel in obj) {
if(_.has(obj, key)) {
if(iterator.call(context, obj[key], key, obj) === breaker)
zurückkehren;
}
}
}
};
// Iterationsprozessor, der Unterschied zu jeder Methode besteht darin, dass Map den Rückgabewert jeder Iteration speichert und ihn als neues Array zurückgibt
_.map = _.collect = function(obj, iterator, context) {
//Array zum Speichern von Rückgabewerten
var results = [];
if(obj == null)
Ergebnisse zurückgeben;
// Priorisieren Sie den Aufruf der von der Hostumgebung bereitgestellten Kartenmethode
if(nativeMap && obj.map === nativeMap)
return obj.map(iterator, context);
// Durch die Elemente in der Sammlung iterieren
every(obj, function(value, index, list) {
// Den Rückgabewert jeder Iteration im Ergebnisarray speichern
results[results.length] = iterator.call(context, value, index, list);
});
//Verarbeitungsergebnisse zurückgeben
if(obj.length === obj.length)
results.length = obj.length;
Ergebnisse zurückgeben;
};
// Legen Sie jedes Element in der Sammlung in den Iterationsprozessor und übergeben Sie den Rückgabewert dieser Iteration als „Memo“ an die nächste Iteration, die im Allgemeinen zum Sammeln von Ergebnissen oder zum Verbinden von Daten verwendet wird
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
// Überprüfe anhand der Anzahl der Parameter, ob ein Anfangswert vorliegt
var initial = arguments.length >
if(obj == null)
obj = [];
// Priorisieren Sie den Aufruf der von der Hostumgebung bereitgestellten Reduzierungsmethode
if(nativeReduce && obj.reduce === nativeReduce && false) {
if(Kontext)
iterator = _.bind(iterator, context);
return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
}
// Durch die Elemente in der Sammlung iterieren
every(obj, function(value, index, list) {
if(!initial) {
// Wenn kein Anfangswert vorhanden ist, wird das erste Element als Anfangswert verwendet. Wenn die Objektsammlung verarbeitet wird, ist der Standardwert der Wert des ersten Attributs
memo = Wert;
initial = wahr;
} anders {
// Zeichnen Sie die Verarbeitungsergebnisse auf und übergeben Sie die Ergebnisse an die nächste Iteration
memo = iterator.call(context, memo, value, index, list);
}
});
if(!initial)
throw new TypeError('Reduzieren eines leeren Arrays ohne Anfangswert');
Rücksendevermerk;
};
// Ähnlich wie beim Reduzieren werden die Elemente in der Sammlung in umgekehrter Richtung iteriert (d. h. vom letzten Element zum ersten Element beginnend).
_.reduceRight = _.foldr = function(obj, iterator, memo, context) {
var initial = arguments.length >
if(obj == null)
obj = [];
// Priorisieren Sie den Aufruf der von der Hostumgebung bereitgestellten ReduceRight-Methode
if(nativeReduceRight && obj.reduceRight === nativeReduceRight) {
if(Kontext)
iterator = _.bind(iterator, context);
return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
}
//Kehrt die Reihenfolge der Elemente in der Sammlung um
var reversed = _.toArray(obj).reverse();
if(Kontext && !initial)
iterator = _.bind(iterator, context);
//Daten mit der Reduce-Methode verarbeiten
return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator);
};
// Durchlaufen Sie die Elemente in der Sammlung und geben Sie das erste Element zurück, das die Prozessorüberprüfung bestehen kann
_.find = _.detect = function(obj, iterator, context) {
// Ergebnis speichert das erste Element, das die Überprüfung bestehen kann
var-Ergebnis;
// Durchlaufen Sie die Daten mit der beliebigen Methode und zeichnen Sie die Elemente auf, die die Überprüfung bestehen
// (Wenn Sie den Rückgabestatus des Prozessors während der Iteration überprüfen, wäre es sinnvoller, hier die Each-Methode zu verwenden.)
any(obj, function(value, index, list) {
// Wenn das vom Prozessor zurückgegebene Ergebnis in einen booleschen Typ konvertiert wird und der Wert wahr ist, wird das aktuelle Element aufgezeichnet und zurückgegeben
if(iterator.call(context, value, index, list)) {
Ergebnis = Wert;
return true;
}
});
Rückgabeergebnis;
};
// Ähnlich wie die Find-Methode, aber die Filtermethode zeichnet alle überprüften Elemente in der Sammlung auf
_.filter = _.select = function(obj, iterator, context) {
// Wird zum Speichern eines Arrays von Elementen verwendet, die die Validierung bestehen
var results = [];
if(obj == null)
Ergebnisse zurückgeben;
// Geben Sie dem Aufruf der von der Hostumgebung bereitgestellten Filtermethode Priorität
if(nativeFilter && obj.filter === nativeFilter)
return obj.filter(iterator, context);
// Über die Elemente in der Sammlung iterieren und die vom Prozessor überprüften Elemente in das Array einfügen und zurückgeben
every(obj, function(value, index, list) {
if(iterator.call(context, value, index, list))
Ergebnisse[Ergebnisse.Länge] = Wert;
});
Ergebnisse zurückgeben;
};
// Der gegenteilige Effekt der Filtermethode, nämlich die Rückgabe einer Liste von Elementen, die die Prozessorüberprüfung nicht bestanden haben
_.reject = function(obj, iterator, context) {
var results = [];
if(obj == null)
Ergebnisse zurückgeben;
every(obj, function(value, index, list) {
if(!iterator.call(context, value, index, list))
Ergebnisse[Ergebnisse.Länge] = Wert;
});
Ergebnisse zurückgeben;
};
//Wenn alle Elemente in der Sammlung die Prozessorüberprüfung bestehen können, wird „true“ zurückgegeben
_.every = _.all = function(obj, iterator, context) {
var result = true;
if(obj == null)
Ergebnis zurückgeben;
// Dem Aufruf jeder von der Host-Umgebung bereitgestellten Methode Priorität einräumen
if(nativeEvery && obj.every === nativeEvery)
return obj.every(iterator, context);
//Durchlaufe die Elemente in der Sammlung
every(obj, function(value, index, list) {
// Dies wird als result = (result && iterator.call(context, value, index, list)) verstanden
// Überprüfen Sie, ob das Ergebnis des Prozessors nach der Konvertierung in den booleschen Typ ein wahrer Wert ist
if(!( result = result && iterator.call(context, value, index, list)))
Rücklaufunterbrecher;
});
return !!result;
};
// Überprüfen Sie, ob ein Element in der Sammlung einen wahren Wert hat, wenn es in einen booleschen Typ konvertiert wird, oder ob es nach der Verarbeitung durch den Prozessor einen wahren Wert hat?
var any = _.some = _.any = function(obj, iterator, context) {
// Wenn keine Prozessorparameter angegeben sind, gibt die Standardprozessorfunktion das Element selbst zurück und bestimmt, ob es ein wahrer Wert ist, indem sie das Element während der Iteration in einen booleschen Typ konvertiert
iterator ||. ( iterator = _.identity);
var result = false;
if(obj == null)
Ergebnis zurückgeben;
// Dem Aufruf einiger von der Host-Umgebung bereitgestellter Methoden Priorität einräumen
if(nativeSome && obj.some === nativeSome)
return obj.some(iterator, context);
//Durchlaufe die Elemente in der Sammlung
every(obj, function(value, index, list) {
if(result || ( result = iterator.call(context, value, index, list)))
Rücklaufunterbrecher;
});
return !!result;
};
// Prüfen, ob es einen Wert in der Sammlung gibt, der genau mit dem Zielparameter übereinstimmt (der Datentyp wird ebenfalls abgeglichen)
_.include = _.contains = function(obj, target) {
var gefunden = false;
if(obj == null)
Rückgabe gefunden;
// Priorisieren Sie den Aufruf der von der Hostumgebung bereitgestellten Array.prototype.indexOf-Methode
if(nativeIndexOf && obj.indexOf === nativeIndexOf)
return obj.indexOf(target) != -1;
// Mit der Methode „any“ über die Elemente in der Sammlung iterieren und überprüfen, ob Wert und Typ des Elements vollständig mit dem Ziel übereinstimmen.
gefunden = any(obj, function(value) {
Rückgabewert === Ziel;
});
Rückgabe gefunden;
};
// Rufen Sie nacheinander die gleichnamigen Methoden aller Elemente in der Sammlung auf, beginnend mit dem dritten Parameter, der an die aufrufende Methode des Elements übergeben wird.
// Ein Array zurückgeben, das die Verarbeitungsergebnisse aller Methoden speichert
_.invoke = function(obj, method) {
// Parameter, die beim Aufruf der gleichnamigen Methode übergeben werden (ab dem 3. Parameter)
var args = Slice.call(arguments, 2);
// Rufen Sie nacheinander die Methode jedes Elements auf, fügen Sie das Ergebnis in das Array ein und geben Sie es zurück
return _.map(obj, function(value) {
return (_.isFunction(method) ? method || value : value[method]).apply(value, args);
});
};
// Ein Array durchlaufen, das aus einer Liste von Objekten besteht, und eine Liste von Werten für das angegebene Attribut in jedem Objekt zurückgeben
_.pluck = function(obj, key) {
// Wenn die Eigenschaft in einem Objekt nicht vorhanden ist, undefiniert zurückgeben
return _.map(obj, function(value) {
Rückgabewert[Schlüssel];
});
};
// Den Maximalwert in der Sammlung zurückgeben. Wenn kein vergleichbarer Wert vorhanden ist, wird undefiniert zurückgegeben
_.max = function(obj, iterator, context) {
// Wenn die Sammlung ein Array ist und kein Prozessor verwendet wird, verwenden Sie Math.max, um den Maximalwert zu erhalten
// Im Allgemeinen wird eine Reihe von Daten vom Typ „Zahl“ in einem Array gespeichert.
if(!iterator && _.isArray(obj) && obj[0] === obj[0])
return Math.max.apply(Math, obj);
// Für Nullwerte direkt negative Unendlichkeit zurückgeben
if(!iterator && _.isEmpty(obj))
return -Infinity;
// Ein temporäres Objekt, berechnet, wird verwendet, um den Maximalwert während des Vergleichsprozesses zu speichern (temporär)
var result = {
berechnet: -Unendlich
};
//Durchlaufe die Elemente in der Sammlung
every(obj, function(value, index, list) {
// Wenn der Prozessorparameter angegeben ist, sind die verglichenen Daten der vom Prozessor zurückgegebene Wert, andernfalls wird der Standardwert bei jedem Durchlauf direkt verwendet.
var berechnet = iterator ? iterator.call(context, value, index, list) : value;
// Wenn der Vergleichswert größer als der vorherige Wert ist, fügen Sie den aktuellen Wert in result.value ein
berechnet >= result.computed && ( result = {
Wert: Wert,
berechnet: berechnet
});
});
// Den Maximalwert zurückgeben
return result.value;
};
// Den Mindestwert im Satz zurückgeben. Der Verarbeitungsprozess stimmt mit der Max-Methode überein
_.min = function(obj, iterator, context) {
if(!iterator && _.isArray(obj) && obj[0] === obj[0])
return Math.min.apply(Math, obj);
if(!iterator && _.isEmpty(obj))
Rückkehr zur Unendlichkeit;
var result = {
berechnet: Unendlich
};
every(obj, function(value, index, list) {
var berechnet = iterator ? iterator.call(context, value, index, list) : value;
berechnet < result.computed && ( result = {
Wert: Wert,
berechnet: berechnet
});
});
return result.value;
};
// Zufallszahlen verwenden, damit das Array nicht angeordnet werden muss
_.shuffle = function(obj) {
// gemischte Variablen speichern den Verarbeitungsprozess und die Endergebnisdaten
var shuffled = [], rand;
//Durchlaufe die Elemente in der Sammlung
every(obj, function(value, index, list) {
// Eine Zufallszahl generieren, die Zufallszahl liegt zwischen <0-der aktuell verarbeiteten Zahl>
rand = Math.floor(Math.random() * (index 1));
// Platziere die zufällig erhaltenen Elemente am Ende des gemischten Arrays
shuffled[index] = shuffled[rand];
//Fügen Sie den neuesten Wert an der Position der zuvor erhaltenen Zufallszahl ein
shuffled[rand] = value;
});
// Ein Array zurückgeben, das zufällig gemischte Sammlungselemente speichert.
Rückgabe gemischt;
};
// Ordnen Sie die Elemente in der Sammlung nach bestimmten Feldern oder Werten an
// Im Vergleich zur Array.prototype.sort-Methode unterstützt die sortBy-Methode das Sortieren von Objekten.
_.sortBy = function(obj, val, context) {
// val sollte eine Eigenschaft des Objekts oder eine Prozessorfunktion sein. Wenn es sich um einen Prozessor handelt, sollte er die zu vergleichenden Daten zurückgeben.
var iterator = _.isFunction(val) ? val : function(obj) {
return obj[val];
};
// Aufrufsequenz: _.pluck(_.map().sort());
// Rufen Sie die Methode _.map() auf, um die Sammlung zu durchlaufen, die Elemente in der Sammlung in den Wertknoten einzufügen und die zu vergleichenden Daten in den Elementen in das Kriterienattribut einzufügen
//Rufen Sie die Methode sort() auf, um die Elemente in der Sammlung gemäß den Daten im Kriterienattribut zu sortieren.
// Pluck aufrufen, um die sortierte Objektsammlung abzurufen und zurückzugeben
return _.pluck(_.map(obj, function(value, index, list) {
zurückkehren {
Wert: Wert,
Kriterien: iterator.call(Kontext, Wert, Index, Liste)
};
}).sort(function(left, right) {
var a = left.criteria, b = right.criteria;
if(a ===
ungültig 0)
Rückgabe 1;
if(b ===
ungültig 0)
return -1;
return a < b ? -1 : a >
}), 'Wert');
};
// Teilen Sie die Elemente in der Sammlung entsprechend den vom Prozessor zurückgegebenen Schlüsseln in mehrere Arrays auf
_.groupBy = function(obj, val) {
var result = {};
// val wird zur Gruppierung in eine Prozessorfunktion konvertiert. Wenn val keine Daten vom Funktionstyp sind, werden sie beim Filtern von Elementen als Schlüsselwert verwendet.
var iterator = _.isFunction(val) ? val : function(obj) {
return obj[val];
};
//Durchlaufe die Elemente in der Sammlung
every(obj, function(value, index) {
// Den Rückgabewert des Prozessors als Schlüssel verwenden und dieselben Schlüsselelemente in ein neues Array einfügen
var key = iterator(value, index);
(Ergebnis[Schlüssel] || (Ergebnis[Schlüssel] = [])).push(Wert);
});
// Gruppierte Daten zurückgeben
Ergebnis zurückgeben;
};
_.sortedIndex = function(array, obj, iterator) {
iterator ||. ( iterator = _.identity);
var low = 0, high = array.length;
while(low < high) {
var mid = (niedrig hoch) >>
iterator(array[mid]) < iterator(obj) ?
}
Rückkehr niedrig;
};
//Eine Sammlung in ein Array konvertieren und zurückgeben
// Wird im Allgemeinen zum Konvertieren von Argumenten in Arrays oder zum Konvertieren ungeordneter Objektsammlungen in geordnete Sammlungen in Form von Daten verwendet
_.toArray = function(obj) {
if(!obj)
zurückkehren [];
if(_.isArray(obj))
return Slice.call(obj);
//Argumente in Array konvertieren
if(_.isArguments(obj))
return Slice.call(obj);
if(obj.toArray && _.isFunction(obj.toArray))
return obj.toArray();
//Konvertieren Sie das Objekt in ein Array, das die Werteliste aller Eigenschaften im Objekt enthält (mit Ausnahme der Eigenschaften in der Prototypenkette des Objekts).
return _.values(obj);
};
// Zähle die Anzahl der Elemente in der Sammlung
_.size = function(obj) {
// Wenn die Sammlung ein Array ist, zählen Sie die Anzahl der Array-Elemente
// Wenn es sich bei der Sammlung um ein Objekt handelt, zählen Sie die Anzahl der Eigenschaften im Objekt (mit Ausnahme der Eigenschaften in der Prototypenkette des Objekts).
return _.isArray(obj) ? obj.length : _.keys(obj).length;
};
// Array-bezogene Methoden
// ---------------
// Das erste oder n Elemente eines in der Reihenfolge angegebenen Arrays zurückgeben
_.first = _.head = _.take = function(array, n, Guard) {
// Wenn Parameter n nicht angegeben ist, das erste Element zurückgeben
// Wenn n angegeben ist, ein neues Array zurückgeben, das die angegebene Anzahl von n Elementen in Folge enthält
//Der Guard-Parameter wird verwendet, um zu bestimmen, dass nur das erste Element zurückgegeben wird. Wenn Guard wahr ist, ist die angegebene Zahl n ungültig.
return (n != null) && !guard ? Slice.call(array, 0, n) : array[0];
};
//Ein neues Array zurückgeben, das andere Elemente außer dem ersten Element enthält oder n Elemente ausschließt, die ab dem letzten Element vorwärts angegeben werden
// Der Unterschied zur ersten Methode besteht darin, dass zuerst die Position des erforderlichen Elements vor dem Array bestimmt wird und initial die Position des ausgeschlossenen Elements am Ende des Arrays bestimmt.
_.initial = function(array, n, Guard) {
// Wenn Parameter n nicht übergeben wird, werden standardmäßig andere Elemente außer dem letzten Element zurückgegeben
// Wenn Parameter n übergeben wird, werden andere Elemente außer n Elementen vorwärts beginnend mit dem letzten Element zurückgegeben.
// Guard wird verwendet, um sicherzustellen, dass nur ein Element zurückgegeben wird. Wenn Guard wahr ist, ist die angegebene Zahl n ungültig.
return Slice.call(array, 0, array.length - ((n == null) || Guard ? 1 : n));
};
//Die letzten n Elemente des Arrays oder die angegebenen n Elemente in umgekehrter Reihenfolge zurückgeben
_.last = function(array, n, Guard) {
if((n != null) && !guard) {
// Berechnen und spezifizieren Sie die erhaltene Elementposition n bis zum Ende des Arrays und geben Sie sie als neues Array zurück
return Slice.call(array, Math.max(array.length - n, 0));
} anders {
// Wenn die Zahl nicht angegeben ist oder der Guard wahr ist, wird nur das letzte Element zurückgegeben
return array[array.length - 1];
}
};
// Andere Elemente außer dem ersten oder den angegebenen ersten n Elementen abrufen
_.rest = _.tail = function(array, index, Guard) {
// Berechnen Sie den zweiten Positionsparameter von Slice bis zum Ende des Arrays
// Wenn der Index nicht angegeben ist oder der Schutzwert wahr ist, werden andere Elemente außer dem ersten Element zurückgegeben.
// Wenn der (index == null)-Wert wahr ist, wird der an die Slice-Funktion übergebene Parameter automatisch in 1 konvertiert
return Slice.call(array, (index == null) || Guard ? 1 : Index);
};
// Alle Elemente im Array zurückgeben, deren Werte in true konvertiert werden können, und ein neues Array zurückgeben
// Zu den Werten, die nicht konvertiert werden können, gehören false, 0, '', null, undefiniert, NaN. Diese Werte werden in false konvertiert
_.compact = Funktion(Array) {
return _.filter(array, function(value) {
return !!value;
});
};
// Kombinieren Sie eine mehrdimensionale Zahl zu einem eindimensionalen Array und unterstützen Sie so die tiefe Zusammenführung
// Der Parameter „Shallow“ wird verwendet, um die Tiefe der Zusammenführung zu steuern. Wenn „Shallow“ auf „true“ gesetzt ist, wird nur die erste Ebene zusammengeführt und eine tiefe Zusammenführung wird standardmäßig durchgeführt.
_.flatten = Funktion(Array, flach) {
// Jedes Element im Array durchlaufen und den Rückgabewert als Demo an die nächste Iteration übergeben
return _.reduce(array, function(memo, value) {
// Wenn das Element immer noch ein Array ist, fällen Sie das folgende Urteil:
// – Wenn keine tiefe Zusammenführung durchgeführt wird, verwenden Sie Array.prototype.concat, um das aktuelle Array und die vorherigen Daten zu verbinden.
// – Wenn Deep Merging unterstützt wird, wird die Flatten-Methode iterativ aufgerufen, bis das zugrunde liegende Element kein Array-Typ mehr ist
if(_.isArray(value))
return memo.concat( flach ? Wert : _.flatten(Wert));
// Die Daten (Wert) befinden sich bereits unten und sind kein Array-Typ mehr. Führen Sie die Daten dann in Memo zusammen und geben Sie sie zurück
memo[memo.length] = value;
Rücksendevermerk;
}, []);
};
// Filtern Sie die Differenzdaten im aktuellen Array, die nicht mit den angegebenen Daten übereinstimmen, und geben Sie sie zurück (siehe Kommentar zur Differenzmethode).
_.without = function(array) {
return _.difference(array, Slice.call(arguments, 1));
};
// Daten im Array deduplizieren (zum Vergleich === verwenden)
// Wenn der Parameter isSorted nicht falsch ist, wird die Include-Methode nacheinander für die Elemente im Array aufgerufen, um zu prüfen, ob dieselben Elemente zum Rückgabewert (Array) hinzugefügt wurden.
// Wenn Sie vor dem Aufruf sicherstellen, dass die Daten im Array in der richtigen Reihenfolge angeordnet sind, können Sie isSorted auf true setzen. Dadurch wird derselbe Wert durch den Vergleich mit dem letzten Element ausgeschlossen. Dies ist effizienter als die Standard-Include-Methode .
// Die Uniq-Methode vergleicht standardmäßig die Daten im Array. Wenn der Iteratorprozessor deklariert ist, wird ein Vergleichsarray basierend auf dem Prozessor erstellt. Die Daten im Array haben beim Vergleich Vorrang, aber die einzigen im Array zurückgegebenen Daten end ist immer noch das ursprüngliche Array
_.uniq = _.unique = function(array, isSorted, iterator) {
// Wenn der Iterator-Prozessor verwendet wird, werden die Daten im aktuellen Array zuerst vom Iterator verarbeitet und ein neues verarbeitetes Array zurückgegeben.
// Das neue Array wird als Vergleichsbasis verwendet
var initial = iterator ? _.map(array, iterator) : array;
// Temporäres Array zum Aufzeichnen von Verarbeitungsergebnissen
var results = [];
// Wenn das Array nur zwei Werte enthält, ist es nicht erforderlich, die Include-Methode zum Vergleich zu verwenden. Wenn Sie isSorted auf true setzen, kann dies die Betriebseffizienz verbessern.
if(array.length < 3)
isSorted = true;
// Verwenden Sie die Reduce-Methode, um die Verarbeitungsergebnisse zu iterieren und zu akkumulieren
//Die Anfangsvariable sind die Basisdaten, die verglichen werden müssen. Es kann sich um ein Originalarray oder eine Ergebnismenge des Prozessors handeln (falls ein Iterator festgelegt ist).
_.reduce(initial, function(memo, value, index) {
// Wenn der Parameter isSorted wahr ist, verwenden Sie === direkt, um die letzten Daten im Datensatz zu vergleichen
// Wenn der isSorted-Parameter falsch ist, verwenden Sie die Include-Methode, um mit allen Daten in der Sammlung zu vergleichen
if( isSorted ? _.last(memo) !== value || !memo.length : !_.include(memo, value)) {
//memo zeichnet die nicht doppelten Daten auf, die verglichen wurden
// Abhängig vom Status des Iteratorparameters können die im Memo aufgezeichneten Daten Originaldaten oder vom Prozessor verarbeitete Daten sein
memo.push(Wert);
// Die im Verarbeitungsergebnis-Array gespeicherten Daten sind immer die Daten im ursprünglichen Array
results.push(array[index]);
}
Rücksendevermerk;
}, []);
// Das Verarbeitungsergebnis zurückgeben, das nur nicht doppelte Daten im Array enthält
Ergebnisse zurückgeben;
};
// Die Union-Methode hat die gleiche Wirkung wie die Uniq-Methode. Der Unterschied besteht darin, dass Union die Übergabe mehrerer Arrays als Parameter ermöglicht.
_.union = function() {
// Union führt mehrere Arrays in den Parametern flach zu einem Array-Objekt zusammen und übergibt es zur Verarbeitung an die Uniq-Methode
return _.uniq(_.flatten(arguments, true));
};
// Holen Sie sich das Schnittelement des aktuellen Arrays und eines oder mehrerer anderer Arrays
//Ab dem zweiten Parameter beginnen ein oder mehrere Arrays, die verglichen werden müssen
_.intersection = _.intersect = function(array) {
// Die Restvariable zeichnet andere Array-Objekte auf, die verglichen werden müssen.
var rest = Slice.call(arguments, 1);
// Verwenden Sie die Uniq-Methode, um doppelte Daten im aktuellen Array zu entfernen und wiederholte Berechnungen zu vermeiden
// Filtern Sie die Daten des aktuellen Arrays durch den Prozessor und geben Sie Daten zurück, die die Bedingungen erfüllen (Vergleich derselben Elemente).
return _.filter(_.uniq(array), function(item) {
// Verwenden Sie die Methode every, um zu überprüfen, ob jedes Array die Daten enthält, die verglichen werden müssen.
// Wenn alle Arrays Vergleichsdaten enthalten, geben alle „true“ zurück. Wenn ein Array das Element nicht enthält, geben sie „false“ zurück
return _.every(rest, function(other) {
// Der andere Parameter speichert jedes Array, das verglichen werden muss
// item speichert die Daten, die verglichen werden müssen, im aktuellen Array
// Verwenden Sie die indexOf-Methode, um zu suchen, ob das Element im Array vorhanden ist (siehe Kommentar zur indexOf-Methode).
return _.indexOf(other, item) >= 0;
});
});
};
// Filtern Sie die Differenzdaten im aktuellen Array, die nicht mit den angegebenen Daten übereinstimmen, und geben Sie sie zurück
// Diese Funktion wird im Allgemeinen verwendet, um die angegebenen Daten im Array zu löschen und nach dem Löschen das neue Array abzurufen
// Die Funktion dieser Methode ist äquivalent zu without. Der Methodenparameter without erlaubt nicht, dass Daten in ein Array aufgenommen werden, während der Differenzmethodenparameter als Array empfohlen wird (Sie können auch dieselben Parameter wie without verwenden).
_.difference = function(array) {
// Alle Parameter ab dem zweiten Parameter als Array zusammenführen (nur die erste Ebene zusammenführen, keine tiefe Zusammenführung)
// Die Restvariable speichert die Verifizierungsdaten, die in dieser Methode zum Vergleich mit den Originaldaten verwendet werden.
var rest = _.flatten(slice.call(arguments, 1), true);
// Filtern Sie die zusammengeführten Array-Daten. Die Filterbedingung ist, dass das aktuelle Array nicht die durch den Parameter angegebenen Verifizierungsdaten enthält.
// Kombinieren Sie die Daten, die die Filterbedingungen erfüllen, in einem neuen Array und geben Sie es zurück
return _.filter(array, function(value) {
return !_.include(rest, value);
});
};
//Gibt die Daten an der gleichen Position jedes Arrays wie ein neues zweidimensionales Array zurück. Die Länge des zurückgegebenen Arrays basiert auf der maximalen Array-Länge in den übergebenen Parametern. Die leeren Positionen anderer Arrays werden mit undefiniert gefüllt.
// Die Zip-Methode sollte mehrere Parameter enthalten und jeder Parameter sollte ein Array sein
_.zip = function() {
// Konvertieren Sie die Parameter in ein Array. Zu diesem Zeitpunkt ist args ein zweidimensionales Array
var args = Slice.call(Argumente);
// Berechnen Sie die Länge jedes Arrays und geben Sie den maximalen Längenwert zurück
var length = _.max(_.pluck(args, 'length'));
//Erstelle ein neues leeres Array entsprechend dem maximalen Längenwert, das zum Speichern der Verarbeitungsergebnisse verwendet wird
var results = new Array(length);
//Die maximale Länge der Schleife. In jeder Schleife wird die Pluck-Methode aufgerufen, um die Daten an derselben Position in jedem Array zu erhalten (von 0 bis zur letzten Position in der Reihenfolge).
// Speichern Sie die erhaltenen Daten in einem neuen Array, fügen Sie sie in die Ergebnisse ein und geben Sie sie zurück
for(var i = 0; i < Länge; i )
results[i] = _.pluck(args, "" i);
//Das zurückgegebene Ergebnis ist ein zweidimensionales Array
Ergebnisse zurückgeben;
};
// Nach dem ersten Vorkommen eines Elements im Array suchen und -1 zurückgeben, wenn das Element nicht existiert
// Verwenden Sie ===, um Elemente bei der Suche abzugleichen
_.indexOf = function(array, item, isSorted) {
if(array == null)
return -1;
var i, l;
if(isSorted) {
i = _.sortedIndex(array, item);
return array[i] === item ? i : -1;
}
// Priorisieren Sie den Aufruf der von der Hostumgebung bereitgestellten indexOf-Methode
if(nativeIndexOf && array.indexOf === nativeIndexOf)
return array.indexOf(item);
// Schleife und das erste Vorkommen des Elements zurückgeben
for( i = 0, l = array.length; i < l; i )
if( i im Array && array[i] === item)
gib i zurück;
// Kein Element gefunden, gibt -1 zurück
return -1;
};
//Gibt die Position des letzten Vorkommens eines Elements im Array zurück oder -1, wenn das Element nicht existiert
// Verwenden Sie ===, um Elemente bei der Suche abzugleichen
_.lastIndexOf = function(array, item) {
if(array == null)
return -1;
// Priorisieren Sie den Aufruf der lastIndexOf-Methode, die von der Hostumgebung bereitgestellt wird
if(nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf)
return array.lastIndexOf(item);
var i = array.length;
// Schleife und das letzte Vorkommen des Elements zurückgeben
while(i--)
if( i im Array && array[i] === item)
gib i zurück;
// Kein Element gefunden, gibt -1 zurück
return -1;
};
// Basierend auf dem Intervall und der Schrittgröße eine Reihe von Ganzzahlen generieren und diese als Array zurückgeben
// Der Startparameter stellt die Mindestanzahl dar
// Der Stoppparameter gibt die maximale Anzahl an
// Der Schrittparameter stellt den Schrittwert zwischen der Generierung mehrerer Werte dar.
_.range = function(start, stop, step) {
// Parametersteuerung
if(arguments.length <= 1) {
// Wenn keine Parameter vorhanden sind, Start = 0, Stopp = 0, werden in der Schleife keine Daten generiert und ein leeres Array zurückgegeben.
// Wenn 1 Parameter vorhanden ist, wird dem Parameter Stopp zugewiesen, Start = 0
Stopp = Start ||. 0;
Start = 0;
}// Erzeuge den Schrittwert der Ganzzahl, der Standardwert ist 1
Schritt = Argumente[2] || 1;
// Berechnen Sie den Maximalwert, der basierend auf dem Intervall und der Schrittgröße generiert wird
var len = Math.max(Math.ceil((stop - start) / step), 0);
varidx = 0;
var range = new Array(len);
// Erzeuge eine Liste von Ganzzahlen und speichere sie im Bereichsarray
while(idx < len) {
Bereich[idx] = start;
Start = Schritt;
}
//Listenergebnisse zurückgeben
Rückgabebereich;
};
//Funktionsbezogene Methoden
// -------------------
//Erstelle ein öffentliches Funktionsobjekt zum Festlegen des Prototyps
var ctor = function() {
};
//Binden Sie den Ausführungskontext für eine Funktion. Immer wenn die Funktion aufgerufen wird, zeigt dies in der Funktion auf das Kontextobjekt.
// Beim Binden einer Funktion können Sie gleichzeitig die aufrufenden Parameter an die Funktion übergeben
_.bind = Funktion bind(func, context) {
var gebunden, args;
// Priorisieren Sie den Aufruf der von der Hostumgebung bereitgestellten Bind-Methode
if(func.bind === nativeBind && nativeBind)
return nativeBind.apply(func, Slice.call(arguments, 1));
// Der Parameter func muss ein Funktionstyp sein
if(!_.isFunction(func))
throw new TypeError;
// Die Variable args speichert die dritte Parameterliste ab der Bind-Methode, die bei jedem Aufruf an die Funktion func übergeben wird.
args = Slice.call(arguments, 2);
returnbound = function() {
if(!(diese Instanz der Grenze))
return func.apply(context, sargs.concat(slice.call(arguments)));
ctor.prototype = func.prototype;
var self = neuer ctor;
var result = func.apply(self, args.concat(slice.call(arguments)));
if(Objekt(Ergebnis) === Ergebnis)
Ergebnis zurückgeben;
sich selbst zurückgeben;
};
};
// Binden Sie die angegebene Funktion oder alle Funktionen des Objekts selbst an das Objekt selbst. Wenn die gebundene Funktion aufgerufen wird, zeigt das Kontextobjekt immer auf das Objekt selbst.
// Diese Methode wird im Allgemeinen bei der Verarbeitung von Objektereignissen verwendet, zum Beispiel:
// _(obj).bindAll(); // oder _(obj).bindAll('handlerClick');
// document.addEventListener('click', obj.handlerClick);
// In der handlerClick-Methode ist der Kontext immer noch das obj-Objekt
_.bindAll = function(obj) {
//Der zweite Parameter gibt zunächst den Namen der Funktion an, die gebunden werden muss
var funcs = Slice.call(arguments, 1);
// Wenn kein spezifischer Funktionsname angegeben wird, werden alle Eigenschaften vom Typ Funktion standardmäßig an das Objekt selbst gebunden.
if(Funktionslänge == 0)
funcs = _.functions(obj);
// Schleife und setze alle Funktionskontexte auf das obj-Objekt selbst
// Die einzelnen Methoden selbst durchlaufen nicht die Methoden in der Prototypenkette des Objekts, aber die Funktionsliste wird hier über die Methode _.functions abgerufen, die bereits die Methoden in der Prototypenkette enthält
every(funcs, function(f) {
obj[f] = _.bind(obj[f], obj);
});
return obj;
};
// Die Memoize-Methode gibt eine Funktion zurück, die die Caching-Funktion integriert, den berechneten Wert in einer lokalen Variablen zwischenspeichert und ihn beim nächsten Aufruf direkt zurückgibt.
// Wenn das Berechnungsergebnis ein großes Objekt oder große Daten ist, sollte bei der Verwendung die Speichernutzung berücksichtigt werden.
_.memoize = function(func, hasher) {
//Memo-Objekt zum Speichern zwischengespeicherter Ergebnisse
var memo = {};
// Der Hasher-Parameter sollte eine Funktion sein, die zur Rückgabe eines Schlüssels verwendet wird, der als Identifikator zum Lesen des Caches verwendet wird
// Wenn der Schlüssel nicht angegeben ist, wird standardmäßig der erste Parameter der Funktion als Schlüssel verwendet. Wenn der erste Parameter der Funktion ein zusammengesetzter Datentyp ist, kann ein Schlüssel ähnlich wie „Dieser Schlüssel“ zurückgegeben werden kann zu späteren Berechnungsfehlern führen
hasher ||. ( hasher = _.identity);
// Eine Funktion zurückgeben, die zuerst den Cache überprüft und dann die nicht zwischengespeicherten Daten aufruft
Rückgabefunktion() {
var key = hasher.apply(this, arguments);
return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
};
};
// Ausführung einer Funktion verzögern
// Die Warteeinheit ist ms und der dritte Parameter wird nacheinander an die Ausführungsfunktion übergeben.
_.delay = function(func, wait) {
var args = Slice.call(arguments, 2);
return setTimeout(function() {
return func.apply(null, args);
}, Warten);
};
// Ausführungsfunktion verzögern
// setTimeout in JavaScript wird in einem separaten Funktionsstapel ausgeführt. Die Ausführungszeit liegt, nachdem alle im aktuellen Stapel aufgerufenen Funktionen ausgeführt wurden.
// defer legt die Funktion fest, die nach 1 ms ausgeführt werden soll. Der Zweck besteht darin, die Funktion func in einen separaten Stapel zu legen und zu warten, bis die aktuelle Funktion abgeschlossen ist, bevor sie ausgeführt wird.
// Die Defer-Methode wird im Allgemeinen verwendet, um die Priorität von DOM-Operationen zu verwalten, um einen korrekten logischen Fluss und ein reibungsloseres interaktives Erlebnis zu erreichen.
_.defer = function(func) {
return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
};
// Funktionsdrosselungsmethode Die Drosselmethode wird hauptsächlich verwendet, um die Ausführungshäufigkeit von Funktionen zu steuern. Innerhalb des kontrollierten Zeitintervalls werden häufig aufgerufene Funktionen nicht mehrmals ausgeführt.
// Wenn die Funktion innerhalb des Zeitintervalls mehrmals aufgerufen wird, wird sie nach Ablauf des Zeitintervalls automatisch einmal aufgerufen. Sie müssen nicht warten, bis die Zeit abgelaufen ist, bevor Sie sie manuell aufrufen (bei automatischem Aufruf gibt es keinen Rückgabewert). )
// Die Drosselfunktion wird im Allgemeinen zur Verarbeitung komplexer und häufig aufgerufener Funktionen verwendet. Sie steuert die Aufrufhäufigkeit von Funktionen durch Drosselung und spart Verarbeitungsressourcen.
// Beispielsweise kann die an window.onresize gebundene Ereignisfunktion oder die an element.onmousemove gebundene Ereignisfunktion mit Throttle gepackt werden.
//Die Throttle-Methode gibt eine Funktion zurück, die automatisch func aufruft und die Drosselungssteuerung durchführt
_.throttle = function(func, wait) {
var context, args, timeout, drosseln, mehr, result;
// Die Variable whenDone ruft die Debounce-Methode auf. Wenn die Funktion also mehrmals aufgerufen wird, überschreibt der letzte Aufruf den zuvor aufgerufenen Timer und die Funktion zum Löschen des Status wird nur einmal ausgeführt
//Die Funktion „whenDone“ wird aufgerufen, wenn das Zeitintervall der letzten Funktionsausführung abläuft, wodurch die Drosselung und einige während des aufrufenden Prozesses aufgezeichnete Zustände aufgehoben werden
var whenDone = _.debounce(function() {
mehr = Drosselung = falsch;
}, Warten);
// Eine Funktion zurückgeben und eine Drosselungssteuerung innerhalb der Funktion durchführen
Rückgabefunktion() {
//Speichern Sie den Ausführungskontext und die Parameter der Funktion
context = this;
args = Argumente;
//Die spätere Funktion wird ausgeführt, wenn das Zeitintervall des letzten Funktionsaufrufs abgelaufen ist
var später = function() {
// Löschen Sie das Timeout-Handle, um den nächsten Funktionsaufruf zu erleichtern
Zeitüberschreitung = null;
// more zeichnet auf, ob die Funktion zwischen dem letzten Aufruf und dem Ablauf des Zeitintervalls wiederholt aufgerufen wurde
// Wenn die Funktion wiederholt aufgerufen wird, wird die Funktion nach Ablauf des Zeitintervalls automatisch erneut aufgerufen.
wenn(mehr)
func.apply(context, args);
// whenDone aufrufen, wird verwendet, um den Drosselungsstatus nach dem Zeitintervall zu löschen
whenDone();
};
// Timeout zeichnet das Zeitintervall-Handle der letzten Funktionsausführung auf
// Rufen Sie die spätere Funktion auf, wenn das Timeout-Intervall abläuft. Das Timeout wird später gelöscht und überprüft, ob die Funktion erneut aufgerufen werden muss.
if(!timeout)
timeout = setTimeout(später, warten);
// Die Drosselungsvariable zeichnet auf, ob das Zeitintervall des letzten Anrufs abgelaufen ist, d. h. ob er sich im Drosselungsprozess befindet
// Die Drosselung wird bei jedem Aufruf der Funktion auf „true“ gesetzt, um anzuzeigen, dass eine Drosselung erforderlich ist, und wird auf „false“ gesetzt, wenn das Zeitintervall abläuft (implementiert in der Funktion „whenDone“).
if(throttling) {
// Während des Drosselungsprozesses werden mehrere Aufrufe durchgeführt und ein Status aufgezeichnet, der darauf hinweist, dass die Funktion nach Ablauf des Zeitintervalls automatisch erneut aufgerufen werden muss.
mehr = wahr;
} anders {
// Es befindet sich nicht im Drosselungsprozess. Möglicherweise wurde die Funktion zum ersten Mal aufgerufen, oder das Intervall des letzten Aufrufs ist überschritten.
result = func.apply(context, args);
}
// whenDone aufrufen, wird verwendet, um den Drosselungsstatus nach dem Zeitintervall zu löschen
whenDone();
// Die Drosselungsvariable zeichnet den Drosselungsstatus auf, wenn die Funktion aufgerufen wird.
Drosselung = wahr;
//Das Aufrufergebnis zurückgeben
Ergebnis zurückgeben;
};
};
// Die Debounce-Methode ähnelt der Throttle-Methode und wird zur Funktionsdrosselung verwendet. Der Unterschied zwischen ihnen ist:
// -- Throttle konzentriert sich auf die Ausführungshäufigkeit der Funktion. Die Funktion wird nur einmal innerhalb der angegebenen Häufigkeit ausgeführt.
// -- Die Debounce-Funktion achtet stärker auf das Intervall zwischen Funktionsausführungen, dh die Zeit zwischen zwei Funktionsaufrufen darf nicht kürzer als die angegebene Zeit sein.
// Wenn das Ausführungsintervall zwischen zwei Funktionen kürzer als die Wartezeit ist, wird der Timer gelöscht und neu erstellt. Dies bedeutet, dass die Funktion bei kontinuierlichem und häufigem Aufruf der Funktion erst in der Zeit zwischen einem bestimmten Aufruf und ausgeführt wird Der vorherige Anruf dauert nicht weniger als eine Millisekunde
// Die Debounce-Funktion wird im Allgemeinen verwendet, um Vorgänge zu steuern, deren Ausführung einige Zeit in Anspruch nimmt. Um beispielsweise den Benutzer 200 ms nach Abschluss der Eingabe aufzufordern, können Sie Debounce verwenden, um eine Funktion zu umschließen und an das Onkeyup-Ereignis zu binden .
//------------------------------------------------ ----------------
// @param {Function} func repräsentiert die ausgeführte Funktion
// @param {Number} wait stellt das zulässige Zeitintervall dar. Wiederholte Aufrufe innerhalb dieses Zeitbereichs werden um Warte-Millisekunden verschoben.
// @param {Boolean}„immediate“ gibt an, ob die Funktion unmittelbar nach dem Aufruf ausgeführt wird. „true“ bedeutet, dass sie sofort aufgerufen wird, „false“ bedeutet, dass sie nach Ablauf der Zeit aufgerufen wird.
// Die Debounce-Methode gibt eine Funktion zurück, die automatisch func aufruft und eine Drosselungssteuerung durchführt
_.debounce = function(func, warte, sofort) {
// Timeout wird verwendet, um den Ausführungsstatus des letzten Funktionsaufrufs aufzuzeichnen (Timer-Handle)
// Wenn das Timeout null ist, bedeutet dies, dass der letzte Anruf beendet wurde
var-Timeout;
// Eine Funktion zurückgeben und eine Drosselungssteuerung innerhalb der Funktion durchführen
Rückgabefunktion() {
// Behalte das Kontextobjekt und die Parameter der Funktion
var context = this, args = arguments;
var später = function() {
//Timeout auf null setzen
// Die spätere Funktion wird aufgerufen, wenn die zulässige Zeit abgelaufen ist
// Beim Aufruf dieser Funktion wird angezeigt, dass die letzte Ausführungszeit der Funktion das vereinbarte Zeitintervall überschritten hat und nachfolgende Aufrufe nach dieser Zeit zulässig sind.
Zeitüberschreitung = null;
if(!immediate)
func.apply(context, args);
};
// Wenn die Funktion auf sofortige Ausführung eingestellt ist und das Zeitintervall des letzten Aufrufs abgelaufen ist, rufen Sie die Funktion sofort auf
if(sofort && !timeout)
func.apply(context, args);
//Erstelle einen Timer, um den Aufrufstatus der Funktion zu überprüfen und festzulegen
// Löschen Sie vor dem Erstellen eines Timers das letzte setTimeout-Handle, unabhängig davon, ob die letzte gebundene Funktion ausgeführt wurde.
// Wenn beim Aufruf dieser Funktion die Ausführung der vorherigen Funktion noch nicht begonnen hat (normalerweise, wenn „immediate“ auf „false“ gesetzt ist), wird die Ausführungszeit der Funktion verzögert, sodass das Timeout-Handle neu erstellt wird
clearTimeout(timeout);
// Rufen Sie die spätere Funktion auf, wenn die zulässige Zeit abgelaufen ist
timeout = setTimeout(später, warten);
};
};
// Eine Funktion erstellen, die nur einmal ausgeführt wird. Wenn die Funktion wiederholt aufgerufen wird, wird das Ergebnis der ersten Ausführung zurückgegeben.
// Diese Funktion wird verwendet, um die Logik fester Daten abzurufen und zu berechnen, z. B. den vom Benutzer verwendeten Browsertyp
_.once = function(func) {
// ran zeichnet auf, ob die Funktion ausgeführt wurde
//memo zeichnet das Ergebnis der letzten Ausführung der Funktion auf
var ran = false, Memo;
Rückgabefunktion() {
// Wenn die Funktion bereits ausgeführt wurde, wird das Ergebnis der ersten Ausführung direkt zurückgegeben
if(ran)
Rücksendevermerk;
ran = wahr;
return memo = func.apply(this, arguments);
};
};
// Gibt eine Funktion zurück, die die aktuelle Funktion als Parameter an eine Wrapper-Funktion übergibt
// In der umschlossenen Funktion können Sie die aktuelle Funktion über den ersten Parameter aufrufen und das Ergebnis zurückgeben
// Wird im Allgemeinen für kombinierte Aufrufe mehrerer Prozessverarbeitungsfunktionen mit geringer Kopplung verwendet
_.wrap = function(func, wrapper) {
Rückgabefunktion() {
// Übergeben Sie die aktuelle Funktion als ersten Parameter an die Wrapper-Funktion
var args = [func].concat(slice.call(arguments, 0));
// Das Verarbeitungsergebnis der Wrapper-Funktion zurückgeben
return wrapper.apply(this, args);
};
};
// Kombinieren Sie mehrere Funktionen entsprechend der Reihenfolge der Parameterübergabe. Der Rückgabewert der letzteren Funktion wird als Parameter an die vorherige Funktion übergeben, um die Verarbeitung fortzusetzen.
// _.compose(A, B, C); ist äquivalent zu A(B(C()));
// Der Nachteil dieser Methode besteht darin, dass die Anzahl der von der zugehörigen Funktion verarbeiteten Parameter nur eins sein kann. Wenn mehrere Parameter übergeben werden müssen, können sie über den zusammengesetzten Datentyp Array oder Object zusammengestellt werden.
_.compose = function() {
// Funktionsliste abrufen, alle Parameter müssen vom Typ Funktion sein
var funcs = Argumente;
//Ein Funktionshandle zum Aufrufen zurückgeben
Rückgabefunktion() {
// Führen Sie die Funktionen der Reihe nach von hinten nach vorne aus und übergeben Sie den aufgezeichneten Rückgabewert als Parameter an die vorherige Funktion, um die Verarbeitung fortzusetzen.
var args = Argumente;
for(var i = funcs.length - 1; i >= 0; i--) {
args = [funcs[i].apply(this, args)];
}
//Gib den Rückgabewert des letzten Funktionsaufrufs zurück
return args[0];
};
};
// Eine Funktion zurückgeben, die als Aufrufzähler dient. Wenn die Funktion mehrmals aufgerufen wird (oder mehrmals), wird die Funktion func ausgeführt.
// Die After-Methode wird im Allgemeinen als asynchroner Zähler verwendet. Wenn Sie beispielsweise eine Funktion ausführen müssen, nachdem mehrere AJAX-Anforderungen abgeschlossen sind, können Sie sie verwenden, um sie nach Abschluss jeder AJAX-Anforderung aufzurufen.
_.after = function(times, func) {
// Wenn keine oder ungültige Zeiten angegeben sind, wird func direkt aufgerufen
if(times <= 0)
return func();
// Eine Zählerfunktion zurückgeben
Rückgabefunktion() {
// Jedes Mal, wenn die Zählerfunktion „times“ aufgerufen wird, wird sie um 1 dekrementiert. Nach dem Aufruf von „times“ wird die Funktion „func“ ausgeführt und der Rückgabewert der Funktion „func“ zurückgegeben.
if(--times < 1) {
return func.apply(this, arguments);
}
};
};
// Objektbezogene Methoden
//----------------
// Eine Liste der Attributnamen eines Objekts abrufen (ausgenommen Attribute in der Prototypenkette)
_.keys = nativeKeys ||
Funktion(obj) {
if(obj !== Object(obj))
throw new TypeError('Invalid object');
var-Tasten = [];
//Alle Eigenschaftsnamen des Objekts aufzeichnen und zurückgeben
for(var-Schlüssel in obj)
if(_.has(obj, key))
Schlüssel[Schlüssellänge] = Schlüssel;
Rückgabeschlüssel;
};
// Eine Werteliste aller Eigenschaften in einem Objekt zurückgeben (mit Ausnahme der Eigenschaften in der Prototypenkette)
_.values = function(obj) {
return _.map(obj, _.identity);
};
// Eine Schlüsselliste aller Eigenschaftswerte in einem Objekt vom Funktionstyp abrufen und nach Schlüsselnamen sortieren (einschließlich Eigenschaften in der Prototypenkette).
_.functions = _.methods = function(obj) {
Var-Namen = [];
for(var-Schlüssel in obj) {
if(_.isFunction(obj[key]))
Namen.push(key);
}
Rückkehrnamen.sort();
};
// Kopieren Sie die Eigenschaften eines oder mehrerer Objekte (einschließlich Eigenschaften in der Prototypenkette) in das obj-Objekt und überschreiben Sie sie, wenn Eigenschaften mit demselben Namen vorhanden sind.
_.extend = function(obj) {
// Ein oder mehrere Objekte in jedem Schleifenparameter
every(slice.call(arguments, 1), function(source) {
//Alle Eigenschaften im Objekt in das obj-Objekt kopieren oder überschreiben
for(var prop in source) {
obj[prop] = source[prop];
}
});
return obj;
};
// Ein neues Objekt zurückgeben und die angegebenen Eigenschaften von obj in das neue Objekt kopieren
//Der zweite Parameter beginnt mit dem angegebenen Attributnamen, der kopiert werden muss (unterstützt mehrere Parameter und tiefe Arrays)
_.pick = function(obj) {
//Erstelle ein Objekt zum Speichern der kopierten angegebenen Attribute
var result = {};
// Beginnen Sie mit dem zweiten Parameter und führen Sie ihn zu einem Array zusammen, um die Liste der Attributnamen zu speichern.
every(_.flatten(slice.call(arguments, 1)), function(key) {
// Durchlaufe die Liste der Attributnamen. Wenn das Attribut in obj vorhanden ist, kopiere es in das Ergebnisobjekt.
if(obj eingeben)
result[key] = obj[key];
});
//Das kopierte Ergebnis zurückgeben
Ergebnis zurückgeben;
};
// Kopieren Sie Attribute, die in obj nicht vorhanden sind oder nach der Konvertierung in den booleschen Typ den Wert „false“ haben, von einem oder mehreren im Parameter angegebenen Objekten nach obj
// Wird im Allgemeinen verwendet, um Objekten Standardwerte zuzuweisen
_.defaults = function(obj) {
// Ab dem zweiten Parameter können mehrere Objekte angegeben werden, und die Eigenschaften in diesen Objekten werden der Reihe nach in das Obj-Objekt kopiert (wenn die Eigenschaft im Obj-Objekt nicht vorhanden ist).
every(slice.call(arguments, 1), function(source) {
// Alle Eigenschaften in jedem Objekt durchlaufen
for(var prop in source) {
// Wenn es in obj nicht vorhanden ist oder der Attributwert nach der Konvertierung in einen booleschen Typ falsch ist, kopieren Sie das Attribut nach obj
if(obj[prop] == null)
obj[prop] = source[prop];
}
});
return obj;
};
//Erstelle eine Kopie von obj und gib ein neues Objekt zurück, das den Status aller Eigenschaften und Werte in obj enthält
// Die Klonfunktion unterstützt kein tiefes Kopieren. Wenn beispielsweise eine Eigenschaft in obj ein Objekt speichert, wird das Objekt nicht kopiert.
// Wenn obj ein Array ist, wird ein identisches Array-Objekt erstellt
_.clone = function(obj) {
//Unterstützt keine Nicht-Array- und Objekttypdaten
if(!_.isObject(obj))
return obj;
//Array oder Objekt kopieren und zurückgeben
return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
};
//Eine Funktion ausführen und obj als Parameter an die Funktion übergeben. Nachdem die Funktion ausgeführt wurde, wird schließlich das obj-Objekt zurückgegeben.
// Im Allgemeinen wird die Tap-Methode beim Erstellen einer Methodenkette verwendet, zum Beispiel:
// _(obj).chain().tap(click).tap(mouseover).tap(mouseout);
_.tap = function(obj, interceptor) {
Abfangjäger(obj);
return obj;
};
// Die eq-Funktion wird nur in der isEqual-Methode aufgerufen und dient zum Vergleich, ob die Werte zweier Daten gleich sind.
//Der Unterschied zu === besteht darin, dass eq dem Wert der Daten mehr Aufmerksamkeit schenkt
// Wenn der Vergleich zwischen zwei zusammengesetzten Datentypen erfolgt, wird nicht nur verglichen, ob sie aus derselben Referenz stammen, sondern es wird auch ein tiefer Vergleich durchgeführt (Vergleich der Struktur und Daten der beiden Objekte).
Funktion eq(a, b, stack) {
// Überprüfen Sie, ob die Werte zweier einfacher Datentypen gleich sind
// Bei zusammengesetzten Datentypen gelten sie als gleich, wenn sie aus derselben Referenz stammen
// Wenn der zu vergleichende Wert 0 enthält, prüfen Sie, ob der andere Wert -0 ist, da 0 === -0 wahr ist
// Und 1/0 == 1/-0 ist nicht wahr (1/0-Wert ist Unendlich, 1/-0-Wert ist -Unendlich und Unendlichkeit ist nicht gleich -Unendlich)
if(a === b)
return a !== 0 ||. 1 / a == 1 / b;
// Wenn nach der Konvertierung der Daten in einen booleschen Typ der Wert falsch ist, wird beurteilt, ob die Datentypen der beiden Werte gleich sind (da null gleich undefiniert, falsch, 0 und eine leere Zeichenfolge unter nicht ist). -strenger Vergleich)
if(a == null || b == null)
return a === b;
// Wenn es sich bei den verglichenen Daten um ein mit Underscore gekapseltes Objekt handelt (Objekte mit dem _chain-Attribut gelten als Underscore-Objekte)
// Dann das Objekt auspacken und seine eigenen Daten abrufen (Zugriff über _wrapped) und dann seine eigenen Daten vergleichen.
// Ihre Beziehung ähnelt einem von jQuery gekapselten DOM-Objekt und einem vom Browser selbst erstellten DOM-Objekt
if(a._chain)
a = a._wrapped;
if(b._chain)
b = b._wrapped;
// Wenn das Objekt eine benutzerdefinierte isEqual-Methode bereitstellt (die isEqual-Methode ist hier nicht die isEqual-Methode des Undersocre-Objekts, da das Undersocre-Objekt im vorherigen Schritt entsperrt wurde)
// Verwenden Sie dann die benutzerdefinierte isEqual-Methode des Objekts, um es mit einem anderen Objekt zu vergleichen
if(a.isEqual && _.isFunction(a.isEqual))
return a.isEqual(b);
if(b.isEqual && _.isFunction(b.isEqual))
return b.isEqual(a);
//Überprüfen Sie die Datentypen der beiden Daten
// Den Datentyp von Objekt a abrufen (über die Object.prototype.toString-Methode)
var className = toString.call(a);
// Wenn der Datentyp von Objekt a nicht mit Objekt b übereinstimmt, gelten die beiden Datenwerte ebenfalls als nicht übereinstimmend.
if(className != toString.call(b))
return false;
// Nach der Ausführung hier können Sie sicherstellen, dass die beiden zu vergleichenden Daten zusammengesetzte Datentypen sind und die Datentypen gleich sind.
// Überprüfen Sie den Datentyp der Daten über den Schalter und führen Sie verschiedene Vergleiche für verschiedene Datentypen durch.
// (Arrays und Objekttypen sind hier nicht enthalten, da sie möglicherweise tiefere Daten enthalten, die später verglichen werden)
switch (Klassenname) {
case '[object String]':
// Wenn das, was verglichen wird, ein String-Typ ist (wobei a ein durch new String() erstellter String ist)
// Dann B in ein String-Objekt umwandeln und dann abgleichen (der Abgleich führt hier keine strenge Datentypprüfung durch, da es sich nicht um Referenzen vom selben Objekt handelt)
// Beim Aufruf von == zum Vergleich wird automatisch die toString()-Methode des Objekts aufgerufen und gibt zwei einfache Datentyp-Strings zurück
return a == String(b);
Fall '[Objektnummer]':
// Konvertiere a in eine Zahl durch a. Wenn a vor und nach der Konvertierung nicht gleich ist, wird davon ausgegangen, dass a ein NaN-Typ ist.
// Da NaN und NaN nicht gleich sind, können Sie, wenn der Wert von a NaN ist, nicht einfach a == b zum Abgleichen verwenden, sondern mit derselben Methode prüfen, ob b NaN ist (d. h. b != b).
// Wenn der Wert von a ein Nicht-NaN-Datenwert ist, prüfen Sie, ob a 0 ist, denn wenn b -0 ist, wird 0 === -0 festgelegt (tatsächlich gehören sie logischerweise zu zwei verschiedenen Daten).
return a != a ? b != b : (a == 0 ? 1 / a == 1 / b : a == b);
case '[Objektdatum]':
// Für den Datumstyp wird kein Return oder Break verwendet, daher wird die Ausführung mit dem nächsten Schritt fortgesetzt (unabhängig davon, ob der Datentyp ein boolescher Typ ist, da der boolesche Typ im nächsten Schritt überprüft wird)
case '[object Boolean]':
//Konvertieren Sie ein Datum oder einen booleschen Typ in eine Zahl
// Der Datumstyp wird in einen numerischen Zeitstempel umgewandelt (ungültiges Datumsformat wird in NaN umgewandelt)
// Im booleschen Typ wird true in 1 konvertiert, false wird in 0 konvertiert
// Vergleichen Sie zwei Datumsangaben oder boolesche Typen, um festzustellen, ob sie nach der Konvertierung in Zahlen gleich sind.
return a == b;
case '[object RegExp]':
// Regulärer Ausdruckstyp, greifen Sie über die Quelle auf die Zeichenfolgenform des Ausdrucks zu
// Überprüfen Sie, ob die Zeichenfolgenformen zweier Ausdrücke gleich sind
// Überprüfen Sie, ob die globalen Eigenschaften der beiden Ausdrücke gleich sind (einschließlich g, i, m)
// Wenn sie völlig gleich sind, gelten die beiden Daten als gleich
return a.source == b.source && a.global == b.global && a.multiline == b.multiline && a.ignoreCase == b.ignoreCase;
}// Bei der Ausführung bis zu diesem Punkt sollten die beiden Daten ab vom gleichen Objekt- oder Array-Typ sein
if( typeof a != 'object' || typeof b != 'object')
return false;
// Stack (Heap) ist das leere Array, das intern übergeben wird, wenn isEqual die eq-Funktion aufruft. Es wird auch übergeben, wenn die eq-Methode später in der internen Iteration des Vergleichs von Objekten und Daten aufgerufen wird.
//length zeichnet die Länge des Heaps auf
var length = stack.length;
while(length--) {
// Wenn ein Objekt im Heap mit den Daten a übereinstimmt, gilt es als gleich
if(Stapel[Länge] == a)
return true;
}
//Daten a zum Heap hinzufügen
stack.push(a);
//Definieren Sie einige lokale Variablen
Var-Größe = 0, Ergebnis = wahr;
// Tiefer Vergleich von Objekten und Arrays durch Rekursion
if(className == '[object Array]') {
//Die verglichenen Daten sind vom Array-Typ
// size zeichnet die Länge des Arrays auf
// Ergebnis vergleicht die Längen der beiden Arrays, um festzustellen, ob sie konsistent sind. Wenn die Längen inkonsistent sind, wird das Ergebnis (dh falsch) am Ende der Methode zurückgegeben.
size = a.length;
result = size == b.length;
// Wenn die Längen der beiden Arrays gleich sind
if(result) {
// Rufen Sie die eq-Methode auf, um die Elemente im Array iterativ zu vergleichen (wenn das Array ein zweidimensionales Array oder Objekt enthält, führt die eq-Methode einen tiefen Vergleich durch)
while(size--) {
// Wenn Sie sicherstellen, dass beide Arrays Elemente am aktuellen Index enthalten, rufen Sie die eq-Methode für einen umfassenden Vergleich auf (übergeben Sie die Heap-Daten an die eq-Methode).
// Speichern Sie das Vergleichsergebnis in der Ergebnisvariablen. Wenn das Ergebnis falsch ist (d. h. die während des Vergleichs erhaltenen Daten eines bestimmten Elements sind inkonsistent), stoppen Sie die Iteration
if(!( result = size in a == size in b && eq(a[size], b[size], stack)))
brechen;
}
}
} anders {
//Die verglichenen Daten sind vom Objekttyp
// Wenn die beiden Objekte keine Instanzen derselben Klasse sind (verglichen durch Konstruktoreigenschaften), werden die beiden Objekte als ungleich betrachtet.
if('constructor' in a != 'constructor' in b || a.constructor != b.constructor)
return false;
// Vergleichen Sie die Daten in zwei Objekten gründlich
for(var key in a) {
if(_.has(a, key)) {
// size wird verwendet, um die Anzahl der verglichenen Attribute aufzuzeichnen, da hier die Attribute des a-Objekts durchlaufen und die Daten des Attributs im b-Objekt verglichen werden
// Wenn die Anzahl der Attribute in Objekt b Objekt a überschreitet, gilt die Logik hier, aber die beiden Objekte sind nicht gleich.
Größe ;
// Rufen Sie iterativ die eq-Methode auf, um die Attributwerte in den beiden Objekten gründlich zu vergleichen
// Zeichnen Sie das Vergleichsergebnis in der Ergebnisvariablen auf und stoppen Sie die Iteration, wenn ungleiche Daten verglichen werden.
if(!( result = _.has(b, key) && eq(a[key], b[key], stack)))
brechen;
}
}
// Der Tiefenvergleich ist abgeschlossen. Es kann sichergestellt werden, dass alle Daten in Objekt a und dieselben Daten auch in Objekt b vorhanden sind.
// Überprüfen Sie anhand der Größe (Objektattributlänge), ob die Anzahl der Attribute in Objekt b gleich der von Objekt a ist.
if(result) {
// Alle Eigenschaften in Objekt b durchlaufen
for(Eingabe von b) {
// Wenn die Größe 0 erreicht hat (d. h. die Anzahl der Attribute in Objekt a wurde durchlaufen) und es noch Attribute in Objekt b gibt, dann hat Objekt b mehr Attribute als Objekt a.
if(_.has(b, key) && !(size--))
brechen;
}
// Wenn Objekt b mehr Attribute als Objekt a hat, werden die beiden Objekte als ungleich betrachtet.
Ergebnis = !size;
}
}
// Wenn die Funktion die Ausführung abschließt, entfernen Sie die ersten Daten aus dem Heap (beim Vergleichen von Objekten oder Arrays wird die eq-Methode iteriert und es können mehrere Daten im Heap vorhanden sein).
stack.pop();
//Das zurückgegebene Ergebnis zeichnet das endgültige Vergleichsergebnis auf
Ergebnis zurückgeben;
}
// Vergleichen Sie die Werte zweier Daten (unterstützt zusammengesetzte Datentypen), externe Methode der internen Funktion Gl
_.isEqual = function(a, b) {
return eq(a, b, []);
};
// Überprüfen Sie, ob die Daten leer sind, einschließlich '', false, 0, null, undefiniert, NaN, leeres Array (Array-Länge ist 0) und leeres Objekt (das Objekt selbst hat keine Eigenschaften)
_.isEmpty = function(obj) {
// obj wird in den booleschen Typ konvertiert und der Wert ist falsch
if(obj == null)
return true;
// Prüfen, ob die Objekt- oder Stringlänge 0 ist
if(_.isArray(obj) || _.isString(obj))
return obj.length === 0;
// Überprüfen Sie das Objekt (bei Verwendung einer for-in-Schleife werden zuerst die Eigenschaften des Objekts selbst durchlaufen, gefolgt von den Eigenschaften in der Prototypkette). Wenn also die erste Eigenschaft zum Objekt selbst gehört, ist das Objekt dies nicht ein leeres Objekt
for(var-Schlüssel in obj)
if(_.has(obj, key))
return false;
// Alle Datentypen haben die Überprüfung nicht bestanden und sind leere Daten
return true;
};
// Überprüfen Sie, ob das Objekt ein DOM-Objekt ist
_.isElement = function(obj) {
return !!(obj && obj.nodeType == 1);
};
// Überprüfen Sie, ob das Objekt ein Array-Typ ist. Rufen Sie zunächst die von der Hostumgebung bereitgestellte isArray-Methode auf
_.isArray = nativeIsArray ||
Funktion(obj) {
return toString.call(obj) == '[object Array]';
};
// Überprüfen Sie, ob es sich bei dem Objekt um ein zusammengesetztes Datentypobjekt handelt (d. h. um einen nicht grundlegenden Datentyp „String“, „Boolean“, „Number“, „null“, „undefiniert“).
// Wenn der Basisdatentyp durch new erstellt wird, gehört er auch zum Objekttyp
_.isObject = function(obj) {
return obj === Object(obj);
};
// Vérifiez si une donnée est un objet paramètre d'arguments
_.isArguments = fonction(obj) {
return toString.call(obj) == '[Arguments de l'objet]';
} ;
// Vérifiez la fonction isArguments. Si l'environnement d'exécution ne peut pas vérifier normalement les données de type arguments, redéfinissez la méthode isArguments.
if(!_.isArguments(arguments)) {
// Si l'environnement ne peut pas vérifier le type d'argument via toString, vérifiez-le en appelant la méthode d'arguments de l'appelé unique.
_.isArguments = fonction(obj) {
// L'appelé est un attribut d'arguments, pointant vers une référence à la fonction elle-même à laquelle appartiennent les arguments.
return !!(obj && _.has(obj, 'callee'));
} ;
}
// Vérifiez si l'objet est un type de fonction
_.isFunction = fonction (obj) {
return toString.call(obj) == '[object Function]';
} ;
// Vérifiez si l'objet est un type chaîne
_.isString = fonction (obj) {
return toString.call(obj) == '[objet String]';
} ;
// Vérifiez si l'objet est de type numérique
_.isNumber = fonction (obj) {
return toString.call(obj) == '[numéro d'objet]';
} ;
// Vérifiez si un nombre est un nombre valide et a une plage valide (type de nombre, valeur entre l'infini négatif et l'infini positif)
_.isFinite = fonction (obj) {
return _.isNumber(obj) && isFinite(obj);
} ;
// Vérifiez si les données sont de type NaN (seuls NaN et NaN ne sont pas égaux à toutes les données)
_.isNaN = fonction (obj) {
retourner obj !== obj;
} ;
// Vérifiez si les données sont de type booléen
_.isBoolean = fonction(obj) {
//Prend en charge les données booléennes sous forme littérale et objet
return obj === true || obj === false || toString.call(obj) == '[objet Booléen]';
} ;
// Vérifiez si les données sont de type Date
_.isDate = fonction (obj) {
return toString.call(obj) == '[Object Date]';
} ;
// Vérifiez si les données sont un type d'expression régulière
_.isRegExp = fonction (obj) {
return toString.call(obj) == '[object RegExp]';
} ;
// Vérifiez si les données sont une valeur nulle
_.isNull = fonction(obj) {
retourner obj === null ;
} ;
// Vérifiez si les données sont une valeur non définie
_.isUndéfini = fonction (obj) {
retourner obj ===
vide 0 ;
} ;
// Vérifiez si une propriété appartient à l'objet lui-même, pas à la chaîne de prototypes
_.has = fonction (obj, clé) {
return hasOwnProperty.call(obj, clé);
} ;
// Fonction utilitaire
// ------------------
// Supprime l'objet Underscore nommé par _ (trait de soulignement) et renvoie l'objet Underscore, qui est généralement utilisé pour éviter les conflits de noms ou standardiser les méthodes de dénomination.
// Par exemple:
// var us = _.noConflict(); // Annule le nom _ (trait de soulignement) et stocke l'objet Underscore dans la variable us
// console.log(_); // _ (trait de soulignement) ne peut plus accéder à l'objet Underscore et revient à la valeur avant la définition du trait de soulignement.
_.noConflict = fonction() {
// La variable previousUnderscore enregistre la valeur de _ (trait de soulignement) avant que le trait de soulignement ne soit défini.
root._ = précédentUnderscore ;
rends ceci ;
} ;
// Renvoie la même valeur que le paramètre, généralement utilisée pour convertir une méthode d'acquisition de données en méthode d'acquisition de fonctions (utilisée en interne comme fonction de processeur par défaut lors de la construction de méthodes)
_.identité = fonction (valeur) {
valeur de retour ;
} ;
// Faire exécuter la fonction spécifiée de manière itérative n fois (sans paramètre)
_.times = fonction (n, itérateur, contexte) {
pour (var je = 0; je < n; je )
itérateur.call(contexte, je);
} ;
// Convertit les caractères spéciaux des chaînes HTML en entités HTML, y compris & <
_.escape = fonction (chaîne) {
return ('' chaîne).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/ "/g, '"').replace(/'/g, ''').replace(///g, '/');
} ;
//Spécifie l'attribut d'un objet et renvoie la valeur correspondant à l'attribut. Si l'attribut correspond à une fonction, la fonction sera exécutée et le résultat sera renvoyé.
_.result = fonction (objet, propriété) {
si (objet == nul)
renvoie null ;
// Récupère la valeur de l'objet
var valeur = objet[propriété];
// Si la valeur est une fonction, exécutez-la et renvoyez-la, sinon elle reviendra directement
return _.isFunction(value) ? value.call(object) : valeur;
} ;
//Ajoutez une série de méthodes personnalisées à l'objet Underscore pour étendre le plug-in Underscore
_.mixin = fonction (obj) {
//obj est un objet qui collecte une série de méthodes personnalisées. Ici, la méthode de parcours de l'objet passe par chacune d'entre elles.
chacun(_.fonctions(obj), fonction(nom) {
//Ajoutez des méthodes personnalisées aux objets créés par Underscore via la fonction addToWrapper pour prendre en charge les appels basés sur les objets
// Ajoutez également des méthodes à _ lui-même pour prendre en charge les appels fonctionnels
addToWrapper(nom, _[nom] = obj[nom]);
});
} ;
// Obtenez un identifiant globalement unique, l'identifiant commence à 0 et s'accumule
var idCounter = 0 ;
// prefix représente le préfixe de l'identifiant. Si aucun préfixe n'est spécifié, l'identifiant sera renvoyé directement. Il est généralement utilisé pour créer un identifiant unique pour un objet ou un DOM.
_.uniqueId = fonction (préfixe) {
var identifiant = idCounter ;
retourner le préfixe ? préfixe id : id;
};
// Définit le symbole délimitant le modèle, utilisé dans la méthode modèle
_.templateSettings = {
//Délimiteur du code exécutable JavaScript
évaluer : /<%([sS] ?)%>/g,
// Affiche directement le délimiteur de la variable
interpoler : /<%=([sS] ?)%>/g,
// Délimiteur requis pour afficher le HTML sous forme de chaîne (convertir les symboles spéciaux sous forme de chaîne)
évasion : /<%-([sS] ?)%>/g
} ;
var noMatch = /.^/;
// L'objet escapes enregistre la correspondance entre les symboles spéciaux et les formes de chaîne qui doivent être convertis entre eux, et est utilisé comme index lorsque les deux sont convertis l'un en l'autre.
// Définissez d'abord les caractères spéciaux selon la forme de la chaîne
var échappe = {
'\' : '\',
"'" : "'",
'r' : 'r',
'n' : 'n',
't' : 't',
'u2028' : 'u2028',
'u2029' : 'u2029'
} ;
// Parcourt toutes les chaînes de caractères spéciaux et enregistre la forme de la chaîne en utilisant des caractères spéciaux comme clés
pour (var p dans les évasions)
échappe[échappe[p]] = p;
// Définissez les symboles spéciaux qui doivent être remplacés dans le modèle, notamment la barre oblique inverse, les guillemets simples, le retour chariot, le saut de ligne, la tabulation, le séparateur de ligne, le séparateur de paragraphe.
// Utilisé lors de la conversion de symboles spéciaux sous forme de chaîne en chaîne
var escaper = /\|'|r|n|t|u2028|u2029/g;
// Utilisé lors de l'inversion (remplacement) de symboles spéciaux sous forme de chaîne
var unescaper = /\(\|'|r|n|t|u2028|u2029)/g;
//Inverser les symboles spéciaux dans la chaîne
// Le code source JavaScript qui doit être exécuté dans le modèle doit être inversé avec des symboles spéciaux, sinon s'il apparaît sous la forme d'entités ou de chaînes HTML, une erreur de syntaxe sera générée
var unescape = fonction (code) {
return code.replace(unescaper, function(match, escape) {
retour évasions[évasion] ;
});
} ;
// Méthode d'analyse du modèle de soulignement, utilisée pour remplir des données dans une chaîne de modèle
// Processus d'analyse du modèle :
// 1. Convertir les symboles spéciaux du modèle en chaînes
// 2. Analysez la balise du formulaire d'échappement et analysez le contenu en entités HTML
// 3. Analyser les balises de formulaire d'interpolation et les variables de sortie
// 4. Analysez la balise du formulaire d'évaluation et créez du code JavaScript exécutable
// 5. Générer une fonction de traitement qui peut remplir directement le modèle après avoir obtenu les données et renvoyer la chaîne remplie
// 6. Renvoie la chaîne remplie ou le handle de la fonction de traitement selon les paramètres
//------------------
//Dans le corps du modèle, deux paramètres peuvent être obtenus via des arguments, à savoir les données de remplissage (nommées obj) et l'objet Underscore (nommé _)
_.template = fonction (texte, données, paramètres) {
// Configuration du modèle, si aucun élément de configuration n'est spécifié, l'élément de configuration spécifié dans templateSettings est utilisé.
settings = _.defaults(settings || {}, _.templateSettings);
// Commencez à analyser le modèle en code source exécutable
var source = "__p ='" text.replace(escaper, function(match) {
//Convertir les symboles spéciaux en forme de chaîne
return '\' escapes[match];
}).replace(settings.escape || noMatch, function(match, code) {
// Analyse la balise du formulaire d'échappement <%- %>, convertit le HTML contenu dans la variable en une entité HTML via la fonction _.escape
return "' n_.escape(" unescape(code) ") n'";
}).replace(settings.interpolate || noMatch, function(match, code) {
// Analyse la balise de formulaire d'interpolation <%= %>, connecte le contenu du modèle en tant que variable avec d'autres chaînes, et il sera affiché en tant que variable
return "' n(" unescape(code) ") n'";
}).replace(settings.evaluate || noMatch, function(match, code) {
// Analyse la balise du formulaire d'évaluation <% %>. Le code JavaScript qui doit être exécuté est stocké dans la balise d'évaluation se termine ici et est exécuté en tant que syntaxe JavaScript dans une nouvelle ligne, ainsi que le contenu suivant. est à nouveau utilisé comme caractères Le début de la chaîne, afin que le code JavaScript dans la balise d'évaluation puisse être exécuté normalement.
return "';n" unescape(code) "n;__p ='";
}) "';n";
si(!settings.variable)
source = 'avec(obj||{}){n' source '}n';
source = "var __p='';" "var print=function(){__p =Array.prototype.join.call(arguments, '')};n" source "return __p;n";
// Créez une fonction, utilisez le code source comme corps d'exécution de la fonction et transmettez obj et Underscore comme paramètres à la fonction
var render = new Function(settings.variable || 'obj', '_', source);
// Si les données de remplissage du modèle sont spécifiées, remplacez le contenu du modèle et renvoyez le résultat remplacé
si (données)
return render(données, _);
// Si aucune donnée de remplissage n'est spécifiée, renvoie une fonction qui remplace les données reçues dans le modèle
// Si le même modèle sera rempli plusieurs fois dans le programme, il est recommandé de ne pas spécifier les données de remplissage lors du premier appel. Après avoir obtenu la référence de la fonction de traitement, l'appeler directement améliorera l'efficacité opérationnelle.
var modèle = fonction (données) {
return render.call(this, données, _);
} ;
//Ajoute la chaîne de code source créée à l'objet fonction, généralement utilisée pour le débogage et les tests
template.source = 'function(' (settings.variable || 'obj') '){n' source '}';
//Si aucune donnée de remplissage n'est spécifiée, renvoie le handle de la fonction de traitement
modèle de retour ;
} ;
// Prise en charge du fonctionnement de la chaîne de méthodes de l'objet Underscore, veuillez vous référer à wrapper.prototype.chain
_.chain = fonction (obj) {
return _(obj).chain();
} ;
// L'objet Underscore encapsule les méthodes associées
// ---------------
//Créer un wrapper pour envelopper certaines données brutes
// Tous les objets undersocre sont construits et encapsulés en interne via la fonction wrapper
//La relation interne entre le trait de soulignement et le wrapper :
// - Définissez la variable _ en interne et ajoutez les méthodes liées au soulignement à _, afin que les appels fonctionnels puissent être pris en charge, tels que _.bind()
// - Définir la classe wrapper en interne et pointer l'objet prototype de _ vers le prototype de la classe wrapper
// -Ajoutez des méthodes liées à Underscore au prototype du wrapper, et l'objet _ créé aura des méthodes Underscore
// - Ajoutez les méthodes liées à Array.prototype au prototype du wrapper, et l'objet _ créé aura les méthodes dans Array.prototype
// -new _() crée et renvoie en fait un objet wrapper(), stocke le tableau d'origine dans la variable _wrapped et appelle la méthode correspondante avec la valeur d'origine comme premier paramètre.
var wrapper = fonction (obj) {
//Les données originales sont stockées dans l'attribut _wrapped de l'objet enveloppé
this._wrapped = obj;
} ;
// Pointez l'objet prototype de Underscore vers le prototype du wrapper, donc en ajoutant des méthodes comme le prototype du wrapper, l'objet Underscore aura également la même méthode.
_.prototype = wrapper.prototype;
//Renvoie un objet. Si le trait de soulignement actuel appelle la méthode chain() (c'est-à-dire que l'attribut _chain est vrai), alors un objet Underscore encapsulé est renvoyé, sinon l'objet lui-même est renvoyé.
// fonction résultat
Nach dem Login kopieren