Aufwärmen · Aufgabe 1 von 7
Aufwärmen: Sie führen node main.js Ada 3 aus. Welcher Ausdruck in main.js ist der String "Ada"?
node main.js Ada 3// B1.3 · ca. 33 Min. · Einstieg
Nach dieser Lektion lesen Sie, was nach node main.js eingegeben wurde, beschreiben die Optionen Ihres Befehls mit util.parseArgs und machen aus einem falschen Argument eine klare Meldung statt eines Absturzes.
Danach können Sie
Aufwärmen · Aufgabe 1 von 7
node main.js Ada 3Vorhersagen · Aufgabe 2 von 7
const [a, b] = process.argv.slice(2);
console.log(a + b);Üben · Aufgabe 3 von 7
const args = process.argv.____(2);
console.log(args);Üben · Aufgabe 4 von 7
Üben · Aufgabe 5 von 7
import {parseArgs} from 'node:util';
const {values} = parseArgs({
args: ['--name', 'Ada', '--name', 'Grace'],
options: {name: {type: 'string'}}
});
console.log(values.name);Denksport · Aufgabe 6 von 7
import {parseArgs} from 'node:util';
const {values, positionals} = parseArgs({
options: {verbose: {type: 'boolean', short: 'v'}}
});
console.log(values.verbose, positionals);Anwenden · Aufgabe 7 von 7
Prüfen Sie Ihr Ergebnis anhand dieser Liste
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
Dieses Programm zeigt zuerst, was process.argv enthält, wenn Sie einfach node main.js ausführen: zwei Einträge, das Programm node und das Skript, und nichts dahinter. Dann beschreibt es zwei Optionen, einen Schalter --loud (-l) und --times (-t) mit Standardwert, und gibt parseArgs drei Kommandozeilen als Arrays aus Strings, so wie process.argv.slice(2) sie liefern würde. Achten Sie darauf, wie jeder Wert ankommt: als true, als String oder als Standardwert.
main.js
import {basename} from 'node:path';
import {parseArgs} from 'node:util';
// Run as plain node main.js: no arguments after the script.
console.log(process.argv.length, basename(process.argv[1]), process.argv.slice(2));
const options = {
loud: {type: 'boolean', short: 'l'},
times: {type: 'string', short: 't', default: '1'}
};
// The same parser, given three command lines as arrays of strings.
for (const args of [['Ada'], ['-l', '--times', '3', 'Ada'], ['--times=2', 'Ada', 'Grace']]) {
const {values, positionals} = parseArgs({args, options, allowPositionals: true});
console.log(args.join(' '), '->', values, positionals);
}
Ausführen mit
node main.jsAusgabe
2 main.js []
Ada -> [Object: null prototype] { times: '1' } [ 'Ada' ]
-l --times 3 Ada -> [Object: null prototype] { loud: true, times: '3' } [ 'Ada' ]
--times=2 Ada Grace -> [Object: null prototype] { times: '2' } [ 'Ada', 'Grace' ]Übung 1 von 2
Ein Befehl nimmt einen Text und eine optionale Anzahl: node main.js hello 3. Schreiben Sie readArgs(args); args ist das, was process.argv.slice(2) liefert. Geben Sie {text, times} zurück, times als Zahl, 1, wenn sie fehlt. Werfen Sie einen Error, dessen Meldung mit Usage beginnt, wenn kein Text angegeben ist, und einen Error, wenn times keine ganze Zahl ab 1 ist. Die Funktion bekommt ein Array, statt process.argv selbst zu lesen, damit die Tests jede Kommandozeile ausprobieren können, und sie läuft 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.
Destrukturierung kann einen Standardwert setzen: const [text, count = '1'] = args;
Number(count) macht aus "3" die Zahl 3; Number.isInteger sagt Ihnen, ob das Ergebnis eine ganze Zahl ist.
Ein Argument, das niemand eingegeben hat, ist undefined. Prüfen Sie text === undefined, bevor Sie es verwenden.
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
// args is what process.argv.slice(2) gives: an array of strings.
export function readArgs(args) {
const [text, count = '1'] = args;
if (text === undefined) throw new Error('Usage: node main.js <text> [times]');
const times = Number(count);
if (!Number.isInteger(times) || times < 1) throw new Error('times must be a whole number from 1, got "' + count + '"');
return {text, times};
}
console.log(readArgs(['hello', '3']));
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
// args is what process.argv.slice(2) gives: an array of strings.
export function readArgs(args) {
const text = args[0];
const times = args[1];
return {text, times};
}
console.log(readArgs(['hello', '3']));
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {readArgs} from './main.js';
test('readArgs(["hello", "3"]) ist {text: "hello", times: 3}', () => {
const got = readArgs(['hello', '3']);
assert.deepEqual(got, {text: 'hello', times: 3}, `readArgs(["hello", "3"]) lieferte ${JSON.stringify(got)}`);
});
test('times ist 1, wenn nur der Text angegeben ist', () => {
const got = readArgs(['hi']);
assert.deepEqual(got, {text: 'hi', times: 1}, `readArgs(["hi"]) lieferte ${JSON.stringify(got)}`);
});
test('ohne Argumente: wirft einen Error, der mit Usage beginnt', () => {
assert.throws(() => readArgs([]), {message: /^Usage/}, 'readArgs([]) sollte einen Error werfen, dessen Meldung mit Usage beginnt');
});
test('times, das keine ganze Zahl ab 1 ist, wirft', () => {
assert.throws(() => readArgs(['hi', 'two']), Error, 'readArgs(["hi", "two"]) sollte werfen');
assert.throws(() => readArgs(['hi', '0']), Error, 'readArgs(["hi", "0"]) sollte werfen');
});
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 2
Vervollständigen Sie echo(args); die Funktion liefert den Text, den der Befehl ausgibt. Beschreiben Sie zwei Optionen für parseArgs: --upper (-u), einen Schalter, der die Wörter in Großbuchstaben setzt, und --times (-t), einen String mit dem Standardwert '1', der die Zeile wiederholt, je eine pro Zeile. Erlauben Sie Positionals: Das sind die Wörter, mit Leerzeichen verbunden. Wirft parseArgs, lassen Sie es nicht abstürzen: Geben Sie seine Meldung, einen Zeilenumbruch und USAGE zurück. Probieren Sie node main.js -u -t 2 hello world, dann node --test.
Diese Übung braucht Node.js auf Ihrem Computer (die Browser-Version kann sie nicht ausführen). Dateien und Befehle stehen unten.
Beschreiben Sie jede Option unter ihrem langen Namen: upper: {type: 'boolean', short: 'u'}.
times ist eine String-Option mit default: '1'. Array(Number(values.times)).fill(line).join('\n') wiederholt die Zeile.
Setzen Sie den Aufruf von parseArgs in try/catch und geben Sie im catch error.message + '\n' + USAGE zurück.
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
import {parseArgs} from 'node:util';
export const USAGE = 'Usage: node main.js [--upper] [--times N] <words...>';
// Returns what the command prints for these arguments.
export function echo(args) {
try {
const {values, positionals} = parseArgs({
args,
options: {
upper: {type: 'boolean', short: 'u'},
times: {type: 'string', short: 't', default: '1'}
},
allowPositionals: true
});
const text = positionals.join(' ');
const line = values.upper ? text.toUpperCase() : text;
return Array(Number(values.times)).fill(line).join('\n');
} catch (error) {
return error.message + '\n' + USAGE;
}
}
console.log(echo(process.argv.slice(2)));
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';
export const USAGE = 'Usage: node main.js [--upper] [--times N] <words...>';
// Returns what the command prints for these arguments.
export function echo(args) {
const {values, positionals} = parseArgs({args, options: {}, allowPositionals: true});
return positionals.join(' ');
}
console.log(echo(process.argv.slice(2)));
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {runMain} from './learnrun.js';
import {echo, USAGE} from './main.js';
const attempt = (args) => {
try {
return echo(args);
} catch (error) {
return `warf ${error.message}`;
}
};
test('echo(["hello", "world"]) ist "hello world"', () => {
const got = attempt(['hello', 'world']);
assert.equal(got, 'hello world', `echo(["hello", "world"]) lieferte ${JSON.stringify(got)}`);
});
test('--upper und -u setzen die Wörter in Großbuchstaben', () => {
assert.equal(attempt(['--upper', 'hi']), 'HI', `echo(["--upper", "hi"]) lieferte ${JSON.stringify(attempt(['--upper', 'hi']))}`);
assert.equal(attempt(['-u', 'hi']), 'HI', `echo(["-u", "hi"]) lieferte ${JSON.stringify(attempt(['-u', 'hi']))}`);
});
test('--times 3 wiederholt die Zeile dreimal, je eine pro Zeile', () => {
const got = attempt(['--times', '3', 'hi']);
assert.equal(got, 'hi\nhi\nhi', `echo(["--times", "3", "hi"]) lieferte ${JSON.stringify(got)}`);
});
test('eine unbekannte Option liefert ihre Meldung und die Usage-Zeile', () => {
const got = attempt(['--colour', 'hi']);
assert.ok(got.startsWith("Unknown option '--colour'") && got.endsWith('\n' + USAGE), `echo(["--colour", "hi"]) lieferte ${JSON.stringify(got)}`);
});
test('node main.js -u -t 2 hello world gibt zweimal HELLO WORLD aus', async () => {
const got = (await runMain({args: ['-u', '-t', '2', 'hello', 'world']})).trimEnd();
assert.equal(got, 'HELLO WORLD\nHELLO WORLD', `das Programm gab ${JSON.stringify(got)} aus`);
});
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 herunterladenconst name = process.argv[2];
console.log("Hello, " + name.toUpperCase() + "!");
Was Node.js ausgibt
TypeError: Cannot read properties of undefined (reading 'toUpperCase')Warum, und die Lösung
Mit node main.js ohne etwas dahinter ist process.argv[2] undefined, und eine Methode auf undefined aufzurufen wirft. Prüfen Sie ein Argument, bevor Sie es verwenden: Bei name === undefined geben Sie eine Usage-Zeile wie Usage: node main.js <name> aus und hören auf, oder Sie setzen einen Standardwert mit process.argv[2] ?? "world".
import {parseArgs} from 'node:util';
const {values} = parseArgs({options: {port: {type: 'number'}}});
console.log(values.port);
Was Node.js ausgibt
TypeError [ERR_INVALID_ARG_TYPE]: The "options.port.type" property must be ('string|boolean'). Received type string ('number')Warum, und die Lösung
parseArgs kennt nur zwei Typen: 'boolean' für einen Schalter und 'string' für eine Option mit Wert. Beschreiben Sie den Port als type: 'string' und wandeln Sie selbst um: const port = Number(values.port), geprüft mit Number.isInteger, bevor Sie ihn verwenden. Der Fehler kommt, bevor ein Argument gelesen wird, weil schon die Beschreibung falsch ist.
import {parseArgs} from 'node:util';
// What node main.js --lines 5 notes.txt passes to the program:
const args = ['--lines', '5', 'notes.txt'];
const {values, positionals} = parseArgs({args, options: {lines: {type: 'string'}}});
console.log(values.lines, positionals);
Was Node.js ausgibt
TypeError [ERR_PARSE_ARGS_UNEXPECTED_POSITIONAL]: Unexpected argument 'notes.txt'. This command does not take positional argumentsWarum, und die Lösung
Im Strict-Modus, der Voreinstellung, ist allowPositionals false: Jedes Argument muss eine Option sein, die Sie beschrieben haben. Ein Dateiname wie notes.txt ist ein Positional, also ergänzen Sie allowPositionals: true. Dann ist values.lines gleich '5' und positionals gleich [ 'notes.txt' ].
JavaScript im Browser: die eigene Engine Ihres Browsers in einem abgeschotteten Worker. Syntaxfehler findet acorn 8.18.0, MIT. Lizenz und Quellcode
5 Fragen, ohne Hinweise. Ab 80 % ist die Lektion abgeschlossen.
Erledigen Sie zuerst alle Aufgaben oben, um das Abschlussquiz freizuschalten.