Aufwärmen · Aufgabe 1 von 7
// B1.5 · ca. 45 Min. · Einstieg
Build: ein Trinkgeldrechner für die Kommandozeile
Nach diesem Build schreiben Sie ein Kommandozeilenwerkzeug, das Argumente und Konfiguration liest, Ergebnisse auf stdout ausgibt, Fehler auf stderr mit einem aussagekräftigen Exit-Code meldet und aus package.json-Skripten startet.
Lektion 5 von 5 in B1 Node ausführen und Projektgrundlagen
Danach können Sie
- Ein Werkzeug in reine Funktionen und einen dünnen Einstiegspunkt aufteilen, der process.argv und process.env liest
- Argumente mit util.parseArgs auswerten und Fehler auf stderr mit Exit-Code 2 oder 1 beantworten
- Das Werkzeug über die Skripte "start" und "dev" mit --env-file-if-exists starten und vorhersagen, welche Einstellung gewinnt
Vorhersagen · Aufgabe 2 von 7
Sagen Sie es vorher, bevor Sie weiterlesen. Das fertige Werkzeug liest sein voreingestelltes Trinkgeld aus TIP_PERCENT. In der Shell ist TIP_PERCENT=20 gesetzt, und in .env steht TIP_PERCENT=10. Sie führen den Befehl unten aus. Was ist die erste Zeile, die er ausgibt?
node --env-file=.env main.js 60 --tip 15Üben · Aufgabe 3 von 7
Das Projekt hat noch keine .env-Datei, und das Skript "start" muss mit und ohne eine funktionieren. Setzen Sie das Flag ein.
{ "type": "module", "scripts": { "start": "node ____=.env main.js" } }"start": "node =.env main.js"Üben · Aufgabe 4 von 7
Ordnen Sie jeder Kommandozeile des fertigen Werkzeugs zu, was sie bewirkt.
Üben · Aufgabe 5 von 7
Was ist die letzte Zeile, die dieser Befehl ausgibt?
node main.js 100 -t 10 -p 3Denksport · Aufgabe 6 von 7
Knobelaufgabe. run() liefert für eine unbekannte Option Exit-Code 2, und node --env-file-if-exists=.env main.js 60 --colour endet tatsächlich mit 2. Was gibt echo $? nach derselben Kommandozeile über das Skript "start" aus?
node --run start -- 60 --colour echo $?Anwenden · Aufgabe 7 von 7
Mini-Aufgabe. Geben Sie dem fertigen Werkzeug eine Währung. Beschreiben Sie in run() --currency (-c), einen String, dessen Default CURRENCY aus der Umgebung ist, sonst EUR. Geben Sie sie nach jedem Betrag aus: tip: 9.00 EUR. Schreiben Sie CURRENCY=USD in .env und führen Sie node --run start -- 60 -p 3 aus, dann probieren Sie -c GBP. Starten Sie zuletzt node --run dev, ändern Sie den Default der Währung und speichern Sie: Der Beispielbefehl läuft erneut.
Prüfen Sie Ihr Ergebnis anhand dieser Liste
Selbst programmieren
Lesen Sie das ausgearbeitete Beispiel und lösen Sie dann die Übungen. Ihr Code läuft in Ihrem Browser oder auf Ihrem Computer und wird nie hochgeladen.
Ausgearbeitetes Beispiel
Dieselbe Form, ein anderes Werkzeug: ein Wortzähler
Bevor Sie den Trinkgeldrechner bauen, hier ein fertiges Werkzeug mit derselben Form. node main.js the cat sat zählt die Wörter mit mindestens --min Buchstaben, und MIN_LETTERS aus der Umgebung setzt den Default. run(args, env) liefert {out, err, code}, statt auszugeben. Ein echter Einstiegspunkt endete mit vier Zeilen, die process.argv.slice(2) und process.env übergeben und das Ergebnis umsetzen; diese Demo ruft run() stattdessen mit vier Kommandozeilen auf, sodass Sie jedes Ergebnis auf einmal sehen.
main.js
import {parseArgs} from 'node:util';
const USAGE = 'Usage: node main.js [--min <letters>] <text...>';
// Counts the words of the text that have at least --min letters. Returns what
// to print on stdout and on stderr, and the exit code:
// 0 = done, 1 = a value it cannot use, 2 = wrong usage.
function run(args, env) {
let values, positionals;
try {
({values, positionals} = parseArgs({
args,
options: {min: {type: 'string', short: 'm', default: env.MIN_LETTERS ?? '1'}},
allowPositionals: true
}));
} catch (error) {
return {out: '', err: error.message + '\n' + USAGE + '\n', code: 2};
}
if (positionals.length === 0) return {out: '', err: USAGE + '\n', code: 2};
const min = Number(values.min);
if (!Number.isInteger(min) || min < 1) {
return {out: '', err: 'error: --min must be a whole number from 1, got "' + values.min + '"\n', code: 1};
}
const words = positionals.join(' ').split(' ').filter((word) => word.length >= min);
return {out: words.length + '\n', err: '', code: 0};
}
// A real entry point ends with four lines that touch the process:
// const {out, err, code} = run(process.argv.slice(2), process.env);
// process.stdout.write(out);
// process.stderr.write(err);
// process.exitCode = code;
// This demo calls run() with four command lines instead, and MIN_LETTERS=3
// in place of process.env, as if a .env file had set it.
const env = {MIN_LETTERS: '3'};
for (const args of [['the cat sat on a mat'], ['--min', '1', 'the cat sat on a mat'], ['-m', 'two', 'cat'], []]) {
const {out, err, code} = run(args, env);
console.log('args', args);
console.log(' stdout ' + JSON.stringify(out) + ', stderr ' + JSON.stringify(err) + ', exit code ' + code);
}
Ausführen mit
node main.jsAusgabe
args [ 'the cat sat on a mat' ]
stdout "4\n", stderr "", exit code 0
args [ '--min', '1', 'the cat sat on a mat' ]
stdout "6\n", stderr "", exit code 0
args [ '-m', 'two', 'cat' ]
stdout "", stderr "error: --min must be a whole number from 1, got \"two\"\n", exit code 1
args []
stdout "", stderr "Usage: node main.js [--min <letters>] <text...>\n", exit code 2- Mit MIN_LETTERS=3 als Default zählen nur the, cat, sat und mat: 4. --min 1 auf der Kommandozeile gewinnt, und alle 6 Wörter zählen.
- -m two hat die richtige Form, aber einen unbrauchbaren Wert: eine Fehlerzeile und Exit-Code 1. Gar kein Text ist falsche Bedienung: die Usage-Zeile und 2.
- stdout ist leer, sobald etwas schiefging, also speichert node main.js … > count.txt nie eine Meldung, als wäre sie ein Zählergebnis.
- Die Klammern in ({values, positionals} = parseArgs(…)) sind nötig: Eine Zeile, die mit { beginnt, würde als Block gelesen.
Übungen
Übung 1 von 3
Schritt 1: die Rechnung aufteilen
Schreiben Sie splitBill({amount, tip, people}); alle drei sind Zahlen, und tip ist ein Prozentsatz. Geben Sie {tip, total, each} zurück: den Trinkgeldbetrag, den Betrag plus Trinkgeld und die Summe geteilt durch die Zahl der Personen, jeweils mit Math.round(x * 100) / 100 auf Cent gerundet. 60 mit 15 % Trinkgeld für 3 Personen ergibt also {tip: 9, total: 69, each: 23}. Die Funktion nutzt kein process und gibt nichts aus, deshalb läuft sie auch im Browser.
Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser den JavaScript-Runner herunter (bis zu 0.1 MB) und speichert ihn im Cache. Ihr Code läuft in der eigenen Engine Ihres Browsers und bleibt auf Ihrem Gerät.
Hinweise
Hinweis 1
Das Trinkgeld ist ein Prozentsatz: amount * tip / 100.
Hinweis 2
Jeder Anteil kommt aus der Summe, nicht aus dem Betrag: total / people.
Hinweis 3
Runden Sie alle drei mit einer Hilfsfunktion: const cents = (x) => Math.round(x * 100) / 100;
Eine Lösung zeigen
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
// Step 1: the arithmetic. amount, tip (a percentage) and people are numbers.
// Return the tip, the total and each share, rounded to cents.
export function splitBill({amount, tip, people}) {
const cents = (x) => Math.round(x * 100) / 100;
const tipAmount = cents((amount * tip) / 100);
const total = cents(amount + tipAmount);
return {tip: tipAmount, total, each: cents(total / people)};
}
console.log(splitBill({amount: 60, tip: 15, people: 3}));
Auf dem eigenen Computer ausführen
Installieren Sie Node.js 24 LTS oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.
main.js
// Step 1: the arithmetic. amount, tip (a percentage) and people are numbers.
// Return the tip, the total and each share, rounded to cents.
export function splitBill({amount, tip, people}) {
return {tip: 0, total: amount, each: amount};
}
console.log(splitBill({amount: 60, tip: 15, people: 3}));
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {splitBill} from './main.js';
test('60 mit 15 % Trinkgeld für 3 Personen: tip 9, total 69, each 23', () => {
const got = splitBill({amount: 60, tip: 15, people: 3});
assert.deepEqual(got, {tip: 9, total: 69, each: 23}, `splitBill lieferte ${JSON.stringify(got)}`);
});
test('jeder Anteil wird auf Cent gerundet: 100 mit 10 % für 3 Personen ergibt je 36.67', () => {
const got = splitBill({amount: 100, tip: 10, people: 3});
assert.deepEqual(got, {tip: 10, total: 110, each: 36.67}, `splitBill lieferte ${JSON.stringify(got)}`);
});
test('das Trinkgeld wird auf Cent gerundet: 19.99 mit 15 % ergibt ein Trinkgeld von 3', () => {
const got = splitBill({amount: 19.99, tip: 15, people: 1});
assert.deepEqual(got, {tip: 3, total: 22.99, each: 22.99}, `splitBill lieferte ${JSON.stringify(got)}`);
});
test('0 % Trinkgeld: die Summe ist der Betrag', () => {
const got = splitBill({amount: 80, tip: 0, people: 4});
assert.deepEqual(got, {tip: 0, total: 80, each: 20}, `splitBill lieferte ${JSON.stringify(got)}`);
});
package.json
{
"type": "module"
}
package.json sagt Node.js, dass die .js-Dateien Module sind; lassen Sie die Datei im Ordner.
Programm ausführen:
node main.jsPrüfungen ausführen (learnrun.js muss im selben Ordner liegen):
node --testlearnrun.js herunterladenÜbung 2 von 3
Schritt 2: die Werte prüfen
parseArgs liefert Strings. Schreiben Sie toNumbers({amount, tip, people}), das die drei Strings in Zahlen umwandelt und als {amount, tip, people} zurückgibt. Werfen Sie einen Error, der den ungültigen Wert nennt, wenn einer unbrauchbar ist: Der Betrag muss über 0 liegen, das Trinkgeld bei 0 oder mehr, und people muss eine ganze Zahl ab 1 sein. people "2.5" wirft zum Beispiel einen Error, dessen Meldung 2.5 enthält. Wie splitBill läuft es auch im Browser.
Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser den JavaScript-Runner herunter (bis zu 0.1 MB) und speichert ihn im Cache. Ihr Code läuft in der eigenen Engine Ihres Browsers und bleibt auf Ihrem Gerät.
Hinweise
Hinweis 1
Number("abc") ist NaN, und jeder Vergleich mit NaN ist false. Also ist !(n > 0) für NaN, 0 und -5 gleichermaßen true.
Hinweis 2
Number.isInteger(2.5) ist false; Number.isInteger(3) ist true.
Hinweis 3
Setzen Sie den ursprünglichen Text in die Meldung: 'people must be a whole number from 1, got "' + people + '"'.
Eine Lösung zeigen
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
// Step 2: the values from the command line are strings. Convert them, and
// throw an Error naming the bad value if one cannot be used:
// amount above 0, tip from 0, people a whole number from 1.
export function toNumbers({amount, tip, people}) {
const bill = {amount: Number(amount), tip: Number(tip), people: Number(people)};
if (!(bill.amount > 0)) throw new Error('amount must be a number above 0, got "' + amount + '"');
if (!(bill.tip >= 0)) throw new Error('tip must be a number from 0, got "' + tip + '"');
if (!Number.isInteger(bill.people) || bill.people < 1) throw new Error('people must be a whole number from 1, got "' + people + '"');
return bill;
}
console.log(toNumbers({amount: "60", tip: "15", people: "3"}));
Auf dem eigenen Computer ausführen
Installieren Sie Node.js 24 LTS oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.
main.js
// Step 2: the values from the command line are strings. Convert them, and
// throw an Error naming the bad value if one cannot be used:
// amount above 0, tip from 0, people a whole number from 1.
export function toNumbers({amount, tip, people}) {
return {amount: Number(amount), tip: Number(tip), people: Number(people)};
}
console.log(toNumbers({amount: "60", tip: "15", people: "3"}));
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {toNumbers} from './main.js';
const ok = {amount: '60', tip: '15', people: '3'};
test('"60", "15" und "3" werden zu den Zahlen 60, 15 und 3', () => {
const got = toNumbers(ok);
assert.deepEqual(got, {amount: 60, tip: 15, people: 3}, `toNumbers lieferte ${JSON.stringify(got)}`);
});
test('ein Betrag, der nicht über 0 liegt, wirft: abc, 0, -5', () => {
for (const amount of ['abc', '0', '-5']) {
assert.throws(() => toNumbers({...ok, amount}), Error, `toNumbers mit amount "${amount}" sollte werfen`);
}
});
test('ein Trinkgeld unter 0 oder keine Zahl wirft: -1, ten', () => {
for (const tip of ['-1', 'ten']) {
assert.throws(() => toNumbers({...ok, tip}), Error, `toNumbers mit tip "${tip}" sollte werfen`);
}
});
test('people muss eine ganze Zahl ab 1 sein: 2.5 und 0 werfen', () => {
for (const people of ['2.5', '0']) {
assert.throws(() => toNumbers({...ok, people}), Error, `toNumbers mit people "${people}" sollte werfen`);
}
});
test('die Meldung nennt den ungültigen Wert', () => {
assert.throws(() => toNumbers({...ok, people: '2.5'}), {message: /2\.5/}, 'die Meldung für people "2.5" sollte 2.5 enthalten');
assert.throws(() => toNumbers({...ok, amount: 'abc'}), {message: /abc/}, 'die Meldung für amount "abc" sollte abc enthalten');
});
package.json
{
"type": "module"
}
package.json sagt Node.js, dass die .js-Dateien Module sind; lassen Sie die Datei im Ordner.
Programm ausführen:
node main.jsPrüfungen ausführen (learnrun.js muss im selben Ordner liegen):
node --testlearnrun.js herunterladenÜbung 3 von 3
Schritt 3: der Befehl
bill.js enthält jetzt die fertigen Schritte 1 und 2 und format. main.js funktioniert für node main.js 60 --people 3, scheitert aber still: Jede Meldung geht mit Exit-Code 0 auf stdout. Korrigieren Sie run(): Das voreingestellte Trinkgeld kommt aus env.TIP_PERCENT, sonst 15; --help (-h) liefert die Usage-Zeile auf stdout mit 0; ein parseArgs-Fehler oder ein fehlender Betrag liefert die Meldung und die Usage auf stderr mit 2; ein ungültiger Wert liefert error: und seine Meldung auf stderr mit 1. Prüfen Sie mit node --test.
Diese Übung braucht Node.js auf Ihrem Computer (die Browser-Version kann sie nicht ausführen). Dateien und Befehle stehen unten.
Hinweise
Hinweis 1
Der Default kann aus der Umgebung kommen: default: env.TIP_PERCENT ?? '15'. Er muss ein String sein, und Werte aus process.env sind es.
Hinweis 2
Verwenden Sie zwei try-Blöcke: einen um parseArgs (falsche Bedienung, 2) und einen um toNumbers (ein ungültiger Wert, 1). Dazwischen behandeln Sie values.help und positionals.length !== 1.
Hinweis 3
Deklarieren Sie let values, positionals; vor dem ersten try und weisen Sie in Klammern zu: ({values, positionals} = parseArgs({...}));
Eine Lösung zeigen
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
import {parseArgs} from 'node:util';
import {format, splitBill, toNumbers} from './bill.js';
const USAGE = 'Usage: node main.js <amount> [--tip <percent>] [--people <count>]';
// The whole command as a function of its arguments and environment. It returns
// what to print on stdout and on stderr, and the exit code:
// 0 = done, 1 = a value it cannot use, 2 = wrong usage.
function run(args, env) {
let values, positionals;
try {
({values, positionals} = parseArgs({
args,
options: {
tip: {type: 'string', short: 't', default: env.TIP_PERCENT ?? '15'},
people: {type: 'string', short: 'p', default: '1'},
help: {type: 'boolean', short: 'h'}
},
allowPositionals: true
}));
} catch (error) {
return {out: '', err: error.message + '\n' + USAGE + '\n', code: 2};
}
if (values.help) return {out: USAGE + '\n', err: '', code: 0};
if (positionals.length !== 1) return {out: '', err: USAGE + '\n', code: 2};
try {
const bill = toNumbers({amount: positionals[0], tip: values.tip, people: values.people});
return {out: format(splitBill(bill)), err: '', code: 0};
} catch (error) {
return {out: '', err: 'error: ' + error.message + '\n', code: 1};
}
}
// The only lines that touch the real process.
const {out, err, code} = run(process.argv.slice(2), process.env);
process.stdout.write(out);
process.stderr.write(err);
process.exitCode = code;
Auf dem eigenen Computer ausführen
Installieren Sie Node.js 24 LTS oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.
main.js
import {parseArgs} from 'node:util';
import {format, splitBill, toNumbers} from './bill.js';
const USAGE = 'Usage: node main.js <amount> [--tip <percent>] [--people <count>]';
// Returns what to print on stdout and on stderr, and the exit code:
// 0 = done, 1 = a value it cannot use, 2 = wrong usage.
// It works for 60 --people 3, but every mistake ends up on stdout with code 0.
function run(args, env) {
try {
const {values, positionals} = parseArgs({
args,
options: {
tip: {type: 'string', short: 't', default: '15'},
people: {type: 'string', short: 'p', default: '1'}
},
allowPositionals: true
});
const bill = toNumbers({amount: positionals[0], tip: values.tip, people: values.people});
return {out: format(splitBill(bill)), err: '', code: 0};
} catch (error) {
return {out: error.message + '\n' + USAGE + '\n', err: '', code: 0};
}
}
// The only lines that touch the real process.
const {out, err, code} = run(process.argv.slice(2), process.env);
process.stdout.write(out);
process.stderr.write(err);
process.exitCode = code;
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {runMain} from './learnrun.js';
test('60 --people 3 gibt das Trinkgeld, die Summe und jeden Anteil aus', async () => {
const got = (await runMain({args: ['60', '--people', '3']})).trimEnd();
assert.equal(got, 'tip: 9.00\ntotal: 69.00\neach: 23.00', `das Programm gab ${JSON.stringify(got)} aus`);
});
test('kurze Optionen funktionieren: -t 10 -p 3 100', async () => {
const got = (await runMain({args: ['-t', '10', '-p', '3', '100']})).trimEnd();
assert.equal(got, 'tip: 10.00\ntotal: 110.00\neach: 36.67', `das Programm gab ${JSON.stringify(got)} aus`);
});
test('TIP_PERCENT setzt das voreingestellte Trinkgeld, und --tip gewinnt trotzdem', async () => {
process.env.TIP_PERCENT = '10';
try {
const byEnv = (await runMain({args: ['60']})).split('\n')[0];
assert.equal(byEnv, 'tip: 6.00', `mit TIP_PERCENT=10 war die erste Zeile ${JSON.stringify(byEnv)}`);
const byFlag = (await runMain({args: ['60', '--tip', '20']})).split('\n')[0];
assert.equal(byFlag, 'tip: 12.00', `mit --tip 20 war die erste Zeile ${JSON.stringify(byFlag)}`);
} finally {
delete process.env.TIP_PERCENT;
}
});
test('--help gibt die Usage-Zeile auf stdout aus', async () => {
const got = await runMain({args: ['--help']});
assert.match(got, /^Usage: node main\.js/, `--help gab ${JSON.stringify(got)} aus`);
});
test('kein Betrag: ein Exit-Code ungleich 0', async () => {
await assert.rejects(runMain(), Error, 'node main.js ohne Betrag endete mit Exit-Code 0');
});
test('eine unbekannte Option: ein Exit-Code ungleich 0', async () => {
await assert.rejects(runMain({args: ['60', '--colour']}), Error, 'node main.js 60 --colour endete mit Exit-Code 0');
});
test('der Betrag abc: ein Exit-Code ungleich 0', async () => {
await assert.rejects(runMain({args: ['abc']}), Error, 'node main.js abc endete mit Exit-Code 0');
});
bill.js
// Pure functions: no process, no console, so they run anywhere.
// Turns the text values from the command line into numbers, or throws.
export function toNumbers({amount, tip, people}) {
const bill = {amount: Number(amount), tip: Number(tip), people: Number(people)};
if (!(bill.amount > 0)) throw new Error('amount must be a number above 0, got "' + amount + '"');
if (!(bill.tip >= 0)) throw new Error('tip must be a number from 0, got "' + tip + '"');
if (!Number.isInteger(bill.people) || bill.people < 1) throw new Error('people must be a whole number from 1, got "' + people + '"');
return bill;
}
// The tip, the total and each person's share, rounded to cents.
export function splitBill({amount, tip, people}) {
const cents = (x) => Math.round(x * 100) / 100;
const tipAmount = cents((amount * tip) / 100);
const total = cents(amount + tipAmount);
return {tip: tipAmount, total, each: cents(total / people)};
}
// The result as the lines the command prints.
export function format({tip, total, each}) {
return 'tip: ' + tip.toFixed(2) + '\ntotal: ' + total.toFixed(2) + '\neach: ' + each.toFixed(2) + '\n';
}
package.json
{
"type": "module"
}
package.json sagt Node.js, dass die .js-Dateien Module sind; lassen Sie die Datei im Ordner.
Programm ausführen:
node main.jsPrüfungen ausführen (learnrun.js muss im selben Ordner liegen):
node --testlearnrun.js herunterladenHäufige Fehler
Eine Zahl als Default einer String-Option
import {parseArgs} from 'node:util';
const {values} = parseArgs({args: ['60'], options: {tip: {type: 'string', short: 't', default: 15}}, allowPositionals: true});
console.log(values.tip);
Was Node.js ausgibt
TypeError [ERR_INVALID_ARG_TYPE]: The "options.tip.default" property must be of type string. Received type number (15)Warum, und die Lösung
Der Default muss zum Typ der Option passen, und eine String-Option braucht einen String: default: '15'. parseArgs prüft das, bevor es ein Argument liest. Der Wert, den Sie zurückbekommen, ist ohnehin ein String, also wandelt toNumbers ihn weiterhin um.
Deklarierten Variablen ohne Klammern zuweisen
import {parseArgs} from 'node:util';
let values, positionals;
{values, positionals} = parseArgs({args: ['60'], options: {}, allowPositionals: true});
console.log(values, positionals);
Was Node.js ausgibt
SyntaxError: Unexpected token '='Warum, und die Lösung
Eine Anweisung, die mit { beginnt, wird als Block gelesen, nicht als Muster, und das = danach ergibt keinen Sinn. Setzen Sie die ganze Zuweisung in Klammern: ({values, positionals} = parseArgs({...}));. Innerhalb eines einzigen try-Blocks können Sie stattdessen in einem Schritt deklarieren und zuweisen: const {values, positionals} = parseArgs({...});.
Einen Optionswert als Zahl verwenden
import {parseArgs} from 'node:util';
const {values} = parseArgs({args: ['--tip', '12.5'], options: {tip: {type: 'string', short: 't', default: '15'}}});
console.log('tip ' + values.tip.toFixed(1) + '%');
Was Node.js ausgibt
TypeError: values.tip.toFixed is not a functionWarum, und die Lösung
values.tip ist der String '12.5', und Strings haben kein toFixed. Wandeln Sie zuerst um und prüfen Sie das Ergebnis: toNumbers macht aus dem Text Zahlen oder wirft mit einer klaren Meldung, bevor irgendetwas damit rechnet.
JavaScript im Browser: die eigene Engine Ihres Browsers in einem abgeschotteten Worker. Syntaxfehler findet acorn 8.18.0, MIT. Lizenz und Quellcode
Abschlussquiz
5 Fragen, ohne Hinweise. Ab 80 % ist die Lektion abgeschlossen.
Erledigen Sie zuerst alle Aufgaben oben, um das Abschlussquiz freizuschalten.