Blog
Möglicherweise benötigen Sie lodash nicht (in Ihrem ES2015-Projekt)

code { display: inline !important; } Dieser Beitrag ist der erste in einer Reihe von ES2015-Beiträgen. In den kommenden zwei Monaten werden wir jede Woche über neue JavaScript-Funktionen berichten. ES2015 bringt eine Menge neuer Funktionen mit sich. Es könnte eine gute Idee sein, zu prüfen, ob Ihre neuen oder bestehenden Projekte tatsächlich eine Bibliothek wie lodash benötigen. Wir werden über einige häufige Verwendungen von lodash-Funktionen sprechen, die einfach durch eine native ES2015-Implementierung ersetzt werden können.
.extend / .merge
Beginnen wir mit .extend und die damit verbundene Funktion .merge. Diese Funktionen werden häufig verwendet, um mehrere Konfigurationseigenschaften in einem einzigen Objekt zu kombinieren.
[javascript]
const dst = { xeb: 0 };
const src1 = { foo: 1, bar: 2 };
const src2 = { foo: 3, baz: 4 };
_.extend(dst, src1, src2);
assert.deepEqual(dst, { xeb: 0, foo: 3, bar: 2, baz: 4 });
[/javascript]
Mit der neuen Methode Object.assign ist das gleiche Verhalten nativ möglich:
[javascript]
const dst2 = { xeb: 0 };
Object.assign(dst2, src1, src2);
assert.deepEqual(dst2, { xeb: 0, foo: 3, bar: 2, baz: 4 });
[/javascript]
Wir verwenden Chai Assertions, um das richtige Verhalten zu bestätigen.
.defaults / .defaultsDeep
Wenn Sie einer Methode viele Parameter übergeben, wird manchmal ein Konfigurationsobjekt verwendet. .defaults und die dazugehörige Funktion .defaultsDeep sind sehr nützlich, um für diese Konfigurationsobjekte Standardwerte in einer bestimmten Struktur zu definieren.
[javascript]
function someFuncExpectingConfig(config) {
_.defaultsDeep(config, {
text: 'default',
colors: {
bgColor: 'black',
fgColor: 'white'
}
});
return config;
}
let config = { colors: { bgColor: 'grey' } };
someFuncExpectingConfig(config);
assert.equal(config.text, 'default');
assert.equal(config.colors.bgColor, 'grey');
assert.equal(config.colors.fgColor, 'white');
[/javascript]
Mit ES2015 können Sie diese Konfigurationsobjekte jetzt in separate Variablen umstrukturieren. Zusammen mit der neuen Standard-Param-Syntax erhalten wir:
[javascript]
function destructuringFuncExpectingConfig({
text = 'default',
colors: {
bgColor: bgColor = 'black',
fgColor: fgColor = 'white' }
}) {
return { text, bgColor, fgColor };
}
const config2 = destructuringFuncExpectingConfig({ colors: { bgColor: 'grey' } } });
assert.equal(config2.text, 'default');
assert.equal(config2.bgColor, 'grey');
assert.equal(config2.fgColor, 'white');
[/javascript]
.find / .findIndex
Die Suche in Arrays mit Hilfe einer Prädikatsfunktion ist ein sauberer Weg, Verhalten und Logik zu trennen.
[javascript]
const arr = [{ name: 'A', id: 123 }, { name: 'B', id: 436 }, { name: 'C', id: 568 }];
function predicateB(val) {
return val.name === 'B';
}
assert.equal(.find(arr, predicateB).id, 436);
assert.equal(.findIndex(arr, predicateB), 1);
[/javascript]
In ES2015 kann dies auf genau dieselbe Weise mit Array.find gemacht werden.
[javascript]
assert.equal(Array.find(arr, predicateB).id, 436);
assert.equal(Array.findIndex(arr, predicateB), 1);
[/javascript]
Beachten Sie, dass wir nicht die erweiterte Array-Syntax arr.find(predicate) verwenden. Dies ist mit Babel, das zum Transpilieren dieses ES2015-Codes verwendet wurde, nicht möglich.
.repeat, .startsWith, .endsWith und .includes
Einige sehr häufige, aber nie nativ unterstützte String-Funktionen sind .repeat um eine Zeichenkette mehrfach zu wiederholen und .startsWith / .endsWith / .includes um zu prüfen, ob eine Zeichenkette mit einer anderen Zeichenkette beginnt, mit ihr endet oder sie einschließt.
[javascript]
assert.equal(.repeat('ab', 3), 'ababab');
assert.isTrue(.startsWith('ab', 'a'));
assert.isTrue(.endsWith('ab', 'b'));
assert.isTrue(.includes('abc', 'b'));
[/javascript]
Strings haben jetzt eine Reihe von neuen prototypischen Funktionen eingebaut:
[javascript]
assert.equal('ab'.repeat(3), 'ababab');
assert.isTrue('ab'.startsWith('a'));
assert.isTrue('ab'.endsWith('b'));
assert.isTrue('abc'.includes('b'));
[/javascript]
.fill
Eine nicht ganz so übliche Funktion, um ein Array mit Standardwerten zu füllen, ohne explizit eine Schleife zu durchlaufen, ist .fill.
[javascript]
const filled = _.fill(new Array(3), 'a', 1);
assert.deepEqual(filled, [, 'a', 'a']);
[/javascript]
Es gibt jetzt einen Ersatz: Array.fill.
[javascript]
const filled2 = Array.fill(new Array(3), 'a', 1);
assert.deepEqual(filled2, [, 'a', 'a']);
[/javascript]
.isNaN, .isFinite
Einige Typüberprüfungen sind recht knifflig, und .isNaN und .isFinite füllen solche Lücken aus.
[javascript]
assert.isTrue(.isNaN(NaN));
assert.isFalse(.isFinite(Infinity));
[/javascript]
Verwenden Sie jetzt einfach die neuen Number-Builtins für diese Prüfungen:
[javascript]
assert.isTrue(Number.isNaN(NaN));
assert.isFalse(Number.isFinite(Infinity));
[/javascript]
.first, .rest
Lodash verfügt über eine Reihe von Funktionen im Stil der funktionalen Programmierung, wie z.B. .first (auch bekannt als .head) und .rest (alias .tail), die den ersten bzw. den Rest der Werte aus einem Array holen.
[javascript]
const elems = [1, 2, 3];
assert.equal(.first(elems), 1);
assert.deepEqual(.rest(elems), [2, 3]);
[/javascript]
Die syntaktische Kraft des rest-Parameters zusammen mit der Destrukturierung ersetzt die Notwendigkeit dieser Funktionen.
[javascript]
const [first, ...rest] = elems;
assert.equal(first, 1);
assert.deepEqual(rest, [2, 3]);
[/javascript]
.restParam
Speziell für ES5 geschrieben, enthält lodash Hilfsfunktionen, um das Verhalten einiger ES2015-Teile zu imitieren. Ein Beispiel ist die Funktion .restParam, die eine Funktion umhüllt und die letzten Parameter als Array an die umhüllte Funktion sendet:
[javascript]
function whatNames(what, names) {
return what + ' ' + names.join(';');
}
const restWhatNames = _.restParam(whatNames);
assert.equal(restWhatNames('hi', 'a', 'b', 'c'), 'hi a;b;c');
[/javascript]
Natürlich können Sie in ES2015 den rest-Parameter einfach wie vorgesehen verwenden.
[javascript]
function whatNamesWithRest(what, ...names) {
return what + ' ' + names.join(';');
}
assert.equal(whatNamesWithRest('hi', 'a', 'b', 'c'), 'hi a;b;c');
[/javascript]
.spread
Ein weiteres Beispiel ist die Funktion .spread, die eine Funktion umhüllt, die ein Array annimmt und das Array als separate Parameter an die umhüllte Funktion sendet:
[javascript]
function whoWhat(who, what) {
return who + ' ' + what;
}
const spreadWhoWhat = _.spread(whoWhat);
const callArgs = ['yo', 'bro'];
assert.equal(spreadWhoWhat(callArgs), 'yo bro');
[/javascript]
Auch in ES2015 wollen Sie den Spread-Operator verwenden.
[javascript]
assert.equal(whoWhat(...callArgs), 'yo bro');
[/javascript]
.values, .keys, .pairs
Es gibt eine Reihe von Funktionen, mit denen Sie alle Werte, Schlüssel oder Wert/Schlüssel-Paare eines Objekts als Array abrufen können:
[javascript]
const bar = { a: 1, b: 2, c: 3 };
const values = .values(bar);
const keys = .keys(bar);
const pairs = .pairs(bar);
assert.deepEqual(values, [1, 2, 3]);
assert.deepEqual(keys, ['a', 'b', 'c']);
assert.deepEqual(pairs, [['a', 1], ['b', 2], ['c', 3]]);
[/javascript]
Jetzt können Sie die Object builtins verwenden:
[javascript]
const values2 = Object.values(bar);
const keys2 = Object.keys(bar);
const pairs2 = Object.entries(bar);
assert.deepEqual(values2, [1, 2, 3]);
assert.deepEqual(keys2, ['a', 'b', 'c']);
assert.deepEqual(pairs2, [['a', 1], ['b', 2], ['c', 3]]);
[/javascript]
.forEach (für Schleifen über Objekteigenschaften)
Um die Eigenschaften eines Objekts in einer Schleife zu durchsuchen, wird häufig eine Hilfsfunktion verwendet, da es einige Einschränkungen gibt, wie z.B. das Überspringen von nicht verwandten Eigenschaften. .forEach kann dafür verwendet werden.
[javascript]
const foo = { a: 1, b: 2, c: 3 };
let sum = 0;
let lastKey = undefined;
_.forEach(foo, function (value, key) {
sum += value;
lastKey = key;
});
assert.equal(sum, 6);
assert.equal(lastKey, 'c');
[/javascript]
Mit ES2015 gibt es einen sauberen Weg, über Object.entries zu schleifen und sie zu destrukturieren:
[javascript]
sum = 0;
lastKey = undefined;
for (let [key, value] of Object.entries(foo)) {
sum += value;
lastKey = key;
}
assert.equal(sum, 6);
assert.equal(lastKey, 'c');
[/javascript]
.get
Bei verschachtelten Strukturen kann ein Pfadselektor oft helfen, die richtige Variable auszuwählen. .get ist für einen solchen Fall gedacht.
[javascript]
const obj = { a: [{}, { b: { c: 3 } }] };
const getC = _.get(obj, 'a[1].b.c');
assert.equal(getC, 3);
[/javascript]
Obwohl ES2015 kein natives Äquivalent für Pfadselektoren hat, können Sie die Destrukturierung als Möglichkeit zur 'Auswahl' eines bestimmten Wertes verwenden.
[javascript]
let a, b, c;
({ a : [, { b: { c } }]} = obj);
assert.equal(c, 3);
[/javascript]
.range Eine sehr Python-mäßige Funktion, die ein Array von Integer-Werten mit einer optionalen Schrittweite erstellt. [javascript] const range = .range(5, 10, 2); assert.deepEqual(range, [5, 7, 9]); [/javascript] Als schöne ES2015-Alternative können Sie eine Generatorfunktion und den Spread-Operator verwenden, um sie zu ersetzen: [javascript] function* rangeGen(from, to, step = 1) { for (let i = from; i < to; i += step) { yield i; } } const range2 = [...rangeGen(5, 10, 2)]; assert.deepEqual(range2, [5, 7, 9]); [/javascript] Ein schöner Nebeneffekt einer Generatorfunktion ist ihre Faulheit. Es ist möglich, den Bereichsgenerator zu verwenden, ohne zuerst das gesamte Array zu generieren, was sehr praktisch sein kann, wenn der Speicherverbrauch minimal sein soll.
Fazit
Genau wie bei der Abkehr von jQuery haben wir gesehen, dass es Alternativen zu einigen Lodash-Funktionen gibt, und dass es besser sein kann, so wenig wie möglich von diesen Funktionen zu verwenden. Denken Sie daran, dass die lodash-Bibliothek eine konsistente API bietet, mit der die Entwickler wahrscheinlich vertraut sind. Tauschen Sie sie nur aus, wenn die Vorteile von ES2015 die Konsistenzgewinne überwiegen (z.B. wenn die Leistung ein Problem ist). Als Referenz finden Sie die obigen Codeschnipsel in diesem Repo. Sie können sie selbst mit webpack und Babel ausführen.
Verfasst von

Albert Brand
Unsere Ideen
Weitere Blogs
Contact



