5172 Stimmen

Wie wird der erste Buchstabe einer Zeichenkette in JavaScript großgeschrieben?

Wie kann ich den ersten Buchstaben einer Zeichenkette in Großbuchstaben umwandeln, ohne die Großschreibung der anderen Buchstaben zu ändern?

Zum Beispiel:

  • "this is a test" "This is a test"
  • "the Eiffel Tower" "The Eiffel Tower"
  • "/index.html" "/index.html"

270voto

Semicolon Punkte 5613

Ich habe in den vorhandenen Antworten keinen Hinweis auf Probleme gefunden, die mit Codepunkte der Astralebene oder Internationalisierung. "Großbuchstaben" bedeutet nicht in jeder Sprache, die eine bestimmte Schrift verwendet, dasselbe.

Ursprünglich habe ich keine Antworten gesehen, die sich mit den Codepunkten der Astralebene befassen. Dort ist eine aber es ist ein bisschen vergraben (wie dieses hier, schätze ich!)


Die meisten der vorgeschlagenen Funktionen sehen wie folgt aus:

function capitalizeFirstLetter(str) {
  return str[0].toUpperCase() + str.slice(1);
}

Einige Großbuchstaben liegen jedoch außerhalb der BMP (multilinguale Basisebene, Codepunkte U+0 bis U+FFFF). Nehmen Sie zum Beispiel diesen Deseret-Text:

capitalizeFirstLetter(""); // ""

Das erste Zeichen wird hier nicht großgeschrieben, da die array-indizierten Eigenschaften von Strings nicht auf "Zeichen" oder Codepunkte* zugreifen. Sie greifen auf UTF-16-Codeeinheiten zu. Dies gilt auch beim Slicing - die Indexwerte zeigen auf Codeeinheiten.

Es ist so, dass die UTF-16-Codeeinheiten 1:1 mit den USV-Codepunkten in zwei Bereichen liegen, U+0 bis U+D7FF und U+E000 bis einschließlich U+FFFF. Die meisten Zeichen in Großbuchstaben fallen in diese beiden Bereiche, aber nicht alle von ihnen.

Ab ES2015 wurde der Umgang damit ein wenig einfacher. String.prototype[@@iterator] ergibt Zeichenketten, die den Codepunkten** entsprechen. Wir können also zum Beispiel Folgendes tun:

function capitalizeFirstLetter([ first, ...rest ]) {
  return [ first.toUpperCase(), ...rest ].join('');
}

capitalizeFirstLetter("") // ""

Bei längeren Zeichenketten ist dies wahrscheinlich nicht sehr effizient*** - wir brauchen den Rest nicht wirklich zu iterieren. Wir könnten verwenden String.prototype.codePointAt um an den ersten (möglichen) Buchstaben zu gelangen, aber wir müssen immer noch bestimmen, wo das Stück beginnen soll. Eine Möglichkeit, die Iteration des Restes zu vermeiden, wäre zu prüfen, ob der erste Codepunkt außerhalb des BMP liegt; ist dies nicht der Fall, beginnt das Slice bei 1, ist dies der Fall, beginnt das Slice bei 2.

function capitalizeFirstLetter(str) {
  const firstCP = str.codePointAt(0);
  const index = firstCP > 0xFFFF ? 2 : 1;

  return String.fromCodePoint(firstCP).toUpperCase() + str.slice(index);
}

capitalizeFirstLetter("") // ""

Sie könnten bitweise Mathematik anstelle von > 0xFFFF aber so ist es wahrscheinlich leichter zu verstehen, und beide Varianten würden das Gleiche bewirken.

Wir können dies auch in ES5 und darunter umsetzen, indem wir diese Logik bei Bedarf ein wenig weiter ausbauen. Es gibt keine intrinsischen Methoden in ES5 für die Arbeit mit Codepoints, so dass wir manuell testen müssen, ob die erste Codeeinheit ein Surrogat**** ist:

function capitalizeFirstLetter(str) {
  var firstCodeUnit = str[0];

  if (firstCodeUnit < '\uD800' || firstCodeUnit > '\uDFFF') {
    return str[0].toUpperCase() + str.slice(1);
  }

  return str.slice(0, 2).toUpperCase() + str.slice(2);
}

capitalizeFirstLetter("") // ""

Zu Beginn habe ich auch Überlegungen zur Internationalisierung erwähnt. Einige davon sind sehr schwierig zu berücksichtigen, weil sie nicht nur Kenntnisse über was Sprache verwendet wird, kann aber auch spezifische Kenntnisse der Wörter der Sprache erfordern. So wird beispielsweise der irische Digraph "mb" am Anfang eines Wortes als "mB" großgeschrieben. Ein anderes Beispiel, das deutsche eszett, steht nie am Anfang eines Wortes (afaik), verdeutlicht aber dennoch das Problem. Das kleingeschriebene Eszett (") wird zu "SS" großgeschrieben, aber "SS" kann entweder zu " oder "ss" kleingeschrieben werden - man muss die deutsche Sprache sehr gut kennen, um zu wissen, was richtig ist!

Das berühmteste Beispiel für diese Art von Problemen ist wahrscheinlich die Türkei. Im türkischen Latein ist die Großbuchstabenform von i , während die Kleinbuchstabenform von I ist - es sind zwei verschiedene Buchstaben. Glücklicherweise haben wir eine Möglichkeit, dies zu berücksichtigen:

function capitalizeFirstLetter([ first, ...rest ], locale) {
  return [ first.toLocaleUpperCase(locale), ...rest ].join('');
}

capitalizeFirstLetter("italy", "en") // "Italy"
capitalizeFirstLetter("italya", "tr") // "talya"

In einem Browser wird die vom Benutzer bevorzugte Sprache durch navigator.language Eine Liste in der Reihenfolge der Präferenzen finden Sie unter navigator.languages und die Sprache eines bestimmten DOM-Elements kann (normalerweise) mit Object(element.closest('[lang]')).lang || YOUR_DEFAULT_HERE in mehrsprachigen Dokumenten.

In Agenten, die Unicode-Eigenschaftszeichenklassen in RegExp unterstützen, die in ES2018 eingeführt wurden, können wir weiter aufräumen, indem wir direkt ausdrücken, an welchen Zeichen wir interessiert sind:

function capitalizeFirstLetter(str, locale=navigator.language) {
  return str.replace(/^\p{CWU}/u, char => char.toLocaleUpperCase(locale));
}

Dies könnte ein wenig optimiert werden, um auch die Großschreibung mehrerer Wörter in einer Zeichenkette mit ziemlich guter Genauigkeit zu handhaben. Die CWU o Änderungen_wenn_großgeschrieben Zeicheneigenschaft passt zu allen Codepunkten, die sich durch Großschreibung verändern. Wir können dies mit einem Digraphenzeichen in Großbuchstaben wie dem niederländischen ausprobieren zum Beispiel:

capitalizeFirstLetter('sselmeer'); // "sselmeer"

Ab Januar 2021 haben alle wichtigen Engines die Funktion der Unicode-Eigenschaftszeichenklasse implementiert, aber je nach Zielbereich können Sie sie möglicherweise noch nicht sicher nutzen. Der letzte Browser, der die Unterstützung eingeführt hat, war Firefox (78; 30. Juni 2020). Sie können überprüfen, ob diese Funktion unterstützt wird, indem Sie die Kangax-Kompatibilitätstabelle . Babel kann verwendet werden, um RegExp-Literale mit Eigenschaftsreferenzen zu äquivalenten Mustern ohne sie zu kompilieren, aber beachten Sie, dass der resultierende Code manchmal enorm sein kann. Sie sollten dies wahrscheinlich nur dann tun, wenn Sie sicher sind, dass der Kompromiss für Ihren Anwendungsfall gerechtfertigt ist.


Aller Wahrscheinlichkeit nach werden sich die Menschen, die diese Frage stellen, nicht mit der Kapitalisierung oder Internationalisierung von Deseret befassen. Aber es ist gut, sich dieser Probleme bewusst zu sein, denn die Wahrscheinlichkeit ist groß, dass sie irgendwann auftauchen, auch wenn sie im Moment noch kein Problem darstellen. Sie sind keine "Randfälle", oder besser gesagt, sie sind nicht by-definition Randfälle - es gibt ein ganzes Land, in dem die meisten Menschen sowieso Türkisch sprechen, und die Verwechslung von Codeeinheiten mit Codepunkten ist eine häufige Fehlerquelle (vor allem in Bezug auf Emoji). Sowohl Strings als auch Sprache sind ziemlich kompliziert!


* Die Codeeinheiten von UTF-16 / UCS2 sind auch Unicode-Codepunkte in dem Sinne, dass z. B. U+D800 technisch gesehen ein Codepunkt ist, aber das ist nicht das, was es hier "bedeutet" ... irgendwie ... obwohl es ziemlich unscharf wird. Was die Surrogate aber definitiv nicht sind, sind USVs (Unicode scalar values).

** Wenn jedoch eine Surrogat-Codeeinheit "verwaist" ist - d. h. nicht Teil eines logischen Paares -, können Sie auch hier Surrogate erhalten.

*** Vielleicht. Ich habe es nicht getestet. Wenn Sie nicht festgestellt haben, dass die Großschreibung einen bedeutenden Engpass darstellt, würde ich mich wahrscheinlich nicht darum kümmern - wählen Sie, was Sie für am klarsten und lesbarsten halten.

**** könnte eine solche Funktion sowohl die erste als auch die zweite Codeeinheit testen wollen, anstatt nur die erste, da es möglich ist, dass die erste Einheit ein verwaistes Surrogat ist. Zum Beispiel die Eingabe " \uD800x " würde das X in Großbuchstaben schreiben, was man erwarten kann oder auch nicht.

169voto

alejandro Punkte 2725

In einem anderen Fall soll der erste Buchstabe groß und der Rest klein geschrieben werden. Die folgenden Fälle haben mich dazu gebracht, diese Funktion zu ändern:

//es5
function capitalize(string) {
    return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
}
capitalize("alfredo")  // => "Alfredo"
capitalize("Alejandro")// => "Alejandro
capitalize("ALBERTO")  // => "Alberto"
capitalize("ArMaNdO")  // => "Armando"

// es6 using destructuring 
const capitalize = ([first,...rest]) => first.toUpperCase() + rest.join('').toLowerCase();

101voto

chovy Punkte 64969

Wenn Sie bereits Folgendes verwenden (oder dies in Erwägung ziehen) Lodash ist die Lösung einfach:

_.upperFirst('fred');
// => 'Fred'

_.upperFirst('FRED');
// => 'FRED'

_.capitalize('fred') //=> 'Fred'

Siehe deren Dokumentation: https://lodash.com/docs#capitalize

_.camelCase('Foo Bar'); //=> 'fooBar'

https://lodash.com/docs/4.15.0#camelCase

_.lowerFirst('Fred');
// => 'fred'

_.lowerFirst('FRED');
// => 'fRED'

_.snakeCase('Foo Bar');
// => 'foo_bar'

Vanilla JavaScript für die erste Großschreibung:

function upperCaseFirst(str){
    return str.charAt(0).toUpperCase() + str.substring(1);
}

97voto

Sterling Bourne Punkte 2660

Dies ist die ECMAScript 6+ Lösung 2018 :

const str = 'the Eiffel Tower';
const newStr = `${str[0].toUpperCase()}${str.slice(1)}`;
console.log('Original String:', str); // the Eiffel Tower
console.log('New String:', newStr); // The Eiffel Tower

84voto

Little Roys Punkte 4695

Es gibt eine sehr einfache Möglichkeit, dies umzusetzen, indem ersetzen. . Für ECMAScript 6:

'foo'.replace(/^./, str => str.toUpperCase())

Ergebnis:

'Foo'

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X