Як зробити першу літеру верхнього регістру рядка в JavaScript?


3757

Як зробити першу букву з великої літери, але не змінити регістр жодної з інших літер?

Наприклад:

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

12
У підкресленні є плагін під назвою underscore.string, який включає в себе це і купу інших чудових інструментів.
Аарон

про що:return str.replace(/(\b\w)/gi,function(m){return m.toUpperCase();});
Мухаммед Умер

110
Простіше:string[0].toUpperCase() + string.substring(1)
dr.dimitru

6
`${s[0].toUpperCase()}${s.slice(1)}`
noego

([initial, ...rest]) => [initial.toUpperCase(), ...rest].join("")
Константин Ван

Відповіді:


5805

Основне рішення:

function capitalizeFirstLetter(string) {
  return string.charAt(0).toUpperCase() + string.slice(1);
}

console.log(capitalizeFirstLetter('foo')); // Foo

Деякі інші відповіді змінюються String.prototype(ця відповідь раніше використовувалася), але я б радив проти цього зараз через технічну ремонтопридатність (важко дізнатися, куди додана функція доprototype та може спричинити конфлікти, якщо інший код використовує те саме ім’я / браузер додає нативну функцію з цим іменем у майбутньому).

... і тоді, на це питання є набагато більше, коли ви розглядаєте питання про інтернаціоналізацію, як це показує дивовижно хороша відповідь (похований нижче).

Якщо ви хочете працювати з точками коду Unicode замість кодових одиниць (наприклад, для обробки символів Unicode за межами базової багатомовної площини), ви можете скористатися тим, що String#[@iterator]працює з кодовими точками, і ви можете використовувати toLocaleUpperCaseдля отримання верхнього регістру, що відповідає правильному мовою:

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

console.log(capitalizeFirstLetter('foo')); // Foo
console.log(capitalizeFirstLetter("𐐶𐐲𐑌𐐼𐐲𐑉")); // "𐐎𐐲𐑌𐐼𐐲𐑉" (correct!)
console.log(capitalizeFirstLetter("italya", 'tr')); // İtalya" (correct in Turkish Latin!)

Для отримання додаткових варіантів інтернаціоналізації див. Оригінальну відповідь нижче .


9
Підрядка розуміється в більшості браузерів, ніж substr
mplungjan

6
додати до karim79 - його, ймовірно, перевищення, щоб зробити його функцією, оскільки javascript зробить те ж саме для змінної без обгортання функції. Я думаю, було б зрозуміліше за допомогою функції, але в іншому випадку, навіщо ускладнювати її обгорткою функції?
Росс

18
Чи не повинні ми такожЗамовитиЗмінити фрагмент (1)?
hasen

177
Ні, тому що ОП навів цей приклад: the Eiffel Tower -> The Eiffel Tower. Плюс, функція називається capitaliseFirstLetterне capitaliseFirstLetterAndLowerCaseAllTheOthers.
заборона-геоінженерія

22
Ніхто не переймається важливим правилом ООП? - Ніколи не редагуйте об’єкти, якими ви не володієте? . До речі, цей одноколісний лайнер виглядає набагато елегантніше:string[0].toUpperCase() + string.substring(1)
dr.dimitru

1349

Ось більш об'єктно-орієнтований підхід:

String.prototype.capitalize = function() {
    return this.charAt(0).toUpperCase() + this.slice(1);
}

Ви б назвали функцію, як-от так:

"hello world".capitalize();

Очікуваний вихід:

"Hello world" 

24
Мені подобається це рішення, тому що це як Рубі, а Рубі - солодке! :) Я return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
реєструю

164
У цьому post-Prototype.js світі не рекомендується змінювати або розширювати натільні об’єкти.
Райан

191
@rxgx - Бугман "не продовжувати" зараз починає відмирати (слава богу), і люди витягують голову з jSand і розуміють, що це лише мовна особливість. Тільки тому, що Prototype.js розширив сам Object на короткий час, не означає, що розширення Natives є поганим. Не слід робити цього, якщо ви пишете код для невідомого споживача (наприклад, сценарій аналітики, який розміщений на випадкових сайтах), але крім цього, це добре.
csuwldcat

43
@csuwldcat Що робити, якщо інша бібліотека, яку ви використовуєте, додає власний капітал, не знаючи про це? Розширення прототипів - це погана форма незалежно від того, чи це зробив Prototype.js, чи ні. Що стосується ES6, то внутрішні матеріали дозволять вам мати свій торт і їсти його також. Я думаю, ви можете збити з пантелику відмирання "бугемана" для людей, які створюють лайки, які відповідають специфікаціям ECMASCRIPT. Ці прокладки є прекрасними, оскільки інша бібліотека, яка додала шим, реалізувала б її таким же чином. Однак додавати власні неспецифічні характеристики слід уникати.
Джастін Мейєр

43
Розширювати тубільців - НАЙКРАЩА погана практика. Навіть якщо ви скажете "о, я ніколи не збираюся використовувати цей код ні з чим іншим", ви (чи хтось інший), ймовірно, будете. Тоді вони витратять три дні, намагаючись з'ясувати якусь дивну математичну помилку, оскільки хтось розширив Number.money (), щоб мати справу з валютою, трохи іншою, ніж у вашій іншій бібліотеці. Серйозно, я бачив, що це трапляється у великій компанії, і не варто нікому часу налагоджувати, щоб з'ясувати бібліотечний диспетчер, який переплутався з прототипами туземців.
freakhead

573

У CSS:

p:first-letter {
    text-transform:capitalize;
}

80
OP просить рішення JS.
Антоніо Макс

129
$ ('# mystring_id'). text (string) .css ('перетворення тексту', 'з великої літери');
ДонМБ

21
Крім того, це впливає лише на відображення рядка - не на фактичне значення. Якщо він у формі, наприклад, значення все одно буде подано як є.
dmansfield

12
Ця відповідь допомогла мені зрозуміти, що рішення CSS насправді є більш підходящим для того, що я роблю. @dudewad: Відповідь, ймовірно, повинна дати відмову від того, що це не рішення JS, але може бути більш підходящим залежно від потреби.
Джошден

58
Для приблизно 80% глядачів, які приходять до цього питання, це буде найкращою відповіддю. Не відповідь на питання , а замість проблеми .
Jivan

290

Ось скорочена версія популярної відповіді, яка отримує першу букву, обробляючи рядок як масив:

function capitalize(s)
{
    return s[0].toUpperCase() + s.slice(1);
}

Оновлення:

Відповідно до коментарів нижче, це не працює в IE 7 або нижче.

Оновлення 2:

Щоб уникнути undefinedпорожніх рядків (див. Коментар @ njzk2 нижче ), ви можете перевірити наявність порожнього рядка:

function capitalize(s)
{
    return s && s[0].toUpperCase() + s.slice(1);
}

23
Це не працюватиме в IE <8, оскільки ці браузери не підтримують індексацію рядків. IE8 сам підтримує його, але лише для рядкових літералів - не для рядкових об'єктів.
Mathias Bynens

52
кому байдуже, ринок IE7 менше 5%! і це, мабуть, стара машина вашої греми та гремпа. Я кажу короткий код FTW!
vsync

@MathiasBynens Чи знаєте ви, чи вплине це на будь-які старі веб-переглядачі, які не є IE, або лише на IE7? Якщо індексація рядкових літералів у 2014 році не впливає на інші браузери, у нас все буде добре. :)
hexalys

3
@vsync Я просто мав на увазі, що в залежності від вашої демографічної характеристики користувачів іноді (хоча з вдячністю все менше і менше, коли ми проходимо 2014 рік і далі) вигідно підтримувати старі браузери, такі як IE7 ...
joshuahedlund

2
@ njzk2 для обробки порожнього рядка, ви можете оновити це: return s && s[0].toUpperCase() + s.slice(1);
joelvh

188

Якщо ви зацікавлені у виконанні декількох різних методів, розміщених:

Ось найшвидші методи, засновані на цьому тесті jsperf (впорядковано від найшвидшого до повільного).

Як бачимо, перші два способи за своєю ефективністю порівнюються, тоді як зміна ефективності String.prototypeє найбільш повільною з точки зору продуктивності.

// 10,889,187 operations/sec
function capitalizeFirstLetter(string) {
    return string[0].toUpperCase() + string.slice(1);
}

// 10,875,535 operations/sec
function capitalizeFirstLetter(string) {
    return string.charAt(0).toUpperCase() + string.slice(1);
}

// 4,632,536 operations/sec
function capitalizeFirstLetter(string) {
    return string.replace(/^./, string[0].toUpperCase());
}

// 1,977,828 operations/sec
String.prototype.capitalizeFirstLetter = function() {
    return this.charAt(0).toUpperCase() + this.slice(1);
}

введіть тут опис зображення


1
Здається, код ініціалізації також не має значення: jsperf.com/capitalize-first-letter-of-string/2
user420667

6
Зауважимо також, що заміна .slice(1)на ще .substr(1)більше підвищить продуктивність.
Пшемек

2
Розумний розгляд. Майте на увазі, що в багатьох випадках хіт продуктивності навіть не помітний: Навіть "найповільніший" підхід оброблятиме 19k рядків за 10 мс. Тому візьміть найзручніший у використанні для вас.
Цитуючи Едді

1
Якщо хтось цікавить (як я), як ефективність цього зросла за останні чотири роки, ops / sec третьої функції на комп'ютері macbook 2018 в 2018 році становить 135 307 869, тобто фактично в 12,4 рази швидше.
Карло Поле

151

Для іншого випадку мені це потрібно, щоб написати велику літеру, а решту написати з малої літери. Наступні випадки змусили мене змінити цю функцію:

//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();

1
"... але не змінювати регістр жодної з інших літер". Це не правильна відповідь на запитання, яке поставив ОП.
Карлос Муньос

2
@ CarlosMuñoz, якщо ви читаєте вступне речення, він каже, що це для іншого випадку.
ТМХ

3
@TomHart Саме тому це не є вирішенням питання. Це має бути коментар чи інше питання та відповідь
Карлос Муньос

15
Я згоден з вами з цього приводу, але я бачу, що багато людей закінчуються тут, які хочуть зробити те, що робить ця відповідь.
TMH

74

Це рішення ECMAScript 6+ для 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


5
.slice()повільніше , ніж .substring(), str[0]було б undefinedдля порожнього рядка і з допомогою літералів шаблонів для об'єднання двох частин вводить тут 8 символів, в той час як +би ввести тільки 3.
Przemek

4
Суть моєї відповіді Prz полягає у демонстрації нових функцій, що підтримуються ES6, зокрема літературних шаблонів, про які не згадувалося в інших публікаціях. Ідея StackOverflow полягає в тому, щоб дати пошуковій "параметри". Вони можуть прийняти концепцію літературних шаблонів, описану в цій відповіді, і поєднати її з мікроскоростними розширеннями, такими як Substring v. Slice, якщо для їх застосування потрібні додаткові збережені мілісекунди. Моя відповідь також не включає тестування одиниць, яке свідчить про те, що ви ніколи не повинні копіювати відповідь StackOverflow безпосередньо. Я припускаю, що розробник візьме мою відповідь і адаптуватиме її.
Стерлінг Борн

Ви нічого не отримуєте, використовуючи тут буквені літерали, і ${}просто додає шум. const newStr = str[0].toUpperCase() + str.slice(1);легше читати.
Борис

1
Погодьтеся, не згоден тоді з тим, що легше читати.
Стерлінг Борн

67

Якщо ви вже (або розглядаєте) використання lodash, рішення легко:

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

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

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

Дивіться їхні документи: 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'

Ваніль js для першого верхнього регістру:

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

11
Я думаю, що перевагу слід надавати ванільній Js, оскільки більшість людей не завантажуватимуть цілі рамки лише з великої літери.
GGG

7
У всіх своїх проектах досі я ніколи не використовував лодаш. Не забувайте також про те, що більшість людей в Google закінчується на цій сторінці, і перелік рамки як альтернативи - це добре, але не як головна відповідь.
GGG

2
Оскільки в інших відповідях використовується ванільний js, приємно мати таку відповідь, оскільки багато з нас використовують лодаш / підкреслення.
Лу Роман

1
Це не правильна відповідь, оскільки ОП просить зараз зробити це в Javascript, а не в бібліотеці Javascript, яка імпортує всю бібліотеку як залежність від вашого проекту. Не використовуйте його.
dudewad

1
Питання ОП у ванілі наприкінці моєї відповіді.
човен

62

Велика літера з усіх слів у рядку:

function ucFirstAllWords( str )
{
    var pieces = str.split(" ");
    for ( var i = 0; i < pieces.length; i++ )
    {
        var j = pieces[i].charAt(0).toUpperCase();
        pieces[i] = j + pieces[i].substr(1);
    }
    return pieces.join(" ");
}

14
Перечитайте запитання: Я хочу використовувати великі літери першого рядка, але не змінювати регістр жодної з інших літер.
JimmyPena

2
Я знаю, що зробив. Я додав би одне, у випадку, якщо весь рядок починається з великої літери: pieces [i] = j + pieces [i] .substr (1) .toLowerCase ();
Малович

4
Ще одне рішення цього випадку: функція capitaliseFirstLetters (s) {return s.split ("") .map (функція (w) {return w.charAt (0) .toUpperCase () + w.substr (1)}). ("")} Може бути хорошим однолінійним, якщо він не введений у функцію.
Люк Ченнінгс

Було б краще спочатку прописати цілу нитку
Magico

Крім цієї функції, що не відповідає на питання, вона насправді також є надскладною. s => s.split(' ').map(x => x[0].toUpperCase() + x.slice(1)).join(' ')
OverCoder

48

Ми могли отримати першого персонажа з одним із моїх улюблених RegExp, схожий на милий смайлик:/^./

String.prototype.capitalize = function () {
  return this.replace(/^./, function (match) {
    return match.toUpperCase();
  });
};

І для всіх кавових наркоманів:

String::capitalize = ->
  @replace /^./, (match) ->
    match.toUpperCase()

... і для всіх хлопців, які думають, що існує кращий спосіб зробити це, не поширюючи натільні прототипи:

var capitalize = function (input) {
  return input.replace(/^./, function (match) {
    return match.toUpperCase();
  });
};

2
Існує кращий спосіб зробити це без зміни прототипу String.
Big McLargeHuge

2
@ davidkennedy85 Звичайно! Але це простий спосіб, не найкращий спосіб ... ;-)
yckart

Шановний пане, мільйон відповідей на це питання! Ваше рішення виглядає ще приємніше в es6. 'Answer'.replace(/^./, v => v.toLowerCase())
stwilz


45

Якщо ви використовуєте underscore.js або Lo-Dash , бібліотека underscore.string забезпечує розширення рядків, включаючи великі літери:

_.capitalize (рядок) Перетворює першу букву рядка в великі регістри.

Приклад:

_.capitalize("foo bar") == "Foo bar"

3
Оскільки, версія 3.0.0 , для Lo-Dash цей метод рядків доступний за замовчуванням. Так само , як описано в цій відповіді: _.capitalize("foo") === "Foo".
бардусний

Також є корисна функція underscore.js, яка називається humanize. Він перетворює підкреслену, камелізовану або штрихову рядок у гуманізовану. Також видаляється пробіл початку і кінця, а також видаляється постфікс "_id".
Степан Захаров

1
Від версії 4 *, Лодаш також малий () інший лист, будьте обережні!
Ігор Лоскутов

45
String.prototype.capitalize = function(allWords) {
   return (allWords) ? // if all words
      this.split(' ').map(word => word.capitalize()).join(' ') : //break down phrase to words then  recursive calls until capitalizing all words
      this.charAt(0).toUpperCase() + this.slice(1); // if allWords is undefined , capitalize only the first word , mean the first char of the whole string
}

І потім:

 "capitalize just the first word".capitalize(); ==> "Capitalize just the first word"
 "capitalize all words".capitalize(true); ==> "Capitalize All Words"

Оновлення листопада 2016 року (ES6), лише для FUN:

const capitalize = (string = '') => [...string].map(    //convert to array with each item is a char of string by using spread operator (...)
    (char, index) => index ? char : char.toUpperCase()  // index true means not equal 0 , so (!index) is the first char which is capitalized by `toUpperCase()` method
 ).join('')                                             //return back to string

тоді capitalize("hello") // Hello


3
Я думаю, що це погане рішення з 2 причин: Модифікація прототипу примітиву - погана ідея. Якщо специфікація зміниться, і вони вирішать вибрати "великі літери" як нове ім'я прототипу, ви порушуєте функціональність основної мови. Крім того, вибрана назва методу погана. На перший погляд, я думаю, що це заздалегідь використає велику частину всього рядка. Використання більш описового імені, наприклад, ucFirst PHP або чогось подібного, може бути кращою ідеєю.
dudewad

Інший ES6 відповідь простіше: const capitalize = ([first,...rest]) => first.toUpperCase() + rest.join('').toLowerCase();.
Дан Даскалеску

44

SHORTEST 3 рішення, 1 і 2 обробляти випадки, коли sрядок є "", nullі undefined:

 s&&s[0].toUpperCase()+s.slice(1)        // 32 char

 s&&s.replace(/./,s[0].toUpperCase())    // 36 char - using regexp

'foo'.replace(/./,x=>x.toUpperCase())    // 31 char - direct on string, ES6


42

Тільки CSS

p::first-letter {
  text-transform: uppercase;
}
  • Незважаючи на те, що викликається ::first-letter, він застосовується до першого символу , тобто у випадку рядка %a, цей селектор буде застосовуватися до цього, %і як такий aне буде використовуватися з великої літери.
  • У IE9 + або IE5.5 + він підтримується у застарілих позначеннях лише однією двокрапкою ( :first-letter).

ES2015 однолінійний

Оскільки у ES2015 є чимало відповідей, але жодна в ES2015 не дозволила б ефективно вирішити оригінальну проблему, я придумав таке:

const capitalizeFirstChar = str => str.charAt(0).toUpperCase() + str.substring(1);

Зауваження

  • parameters => functionце так звана функція стрілки .
  • Я пішов з ім'ям, capitalizeFirstCharа не capitalizeFirstLetterтому, що ОП запитував не код, який використовує велику літери у всій рядку, а найперший знак (якщо це, звичайно, літера).
  • constдає нам можливість заявляти capitalizeFirstCharяк постійну, що бажано, оскільки, як програміст, ви завжди повинні чітко заявляти про свої наміри.
  • У еталоні, який я виконував, не було суттєвої різниці між string.charAt(0)та string[0]. Зауважте, що це string[0]було б undefinedдля порожнього рядка, тому його слід переписати string && string[0], що є занадто багатослівним, порівняно з альтернативним.
  • string.substring(1)швидше, ніж string.slice(1).

Орієнтир

  • 4,956,962 ops / s ± 3,03% для цього розчину,
  • 4,577,946 ops / s ± 1,2% за найбільш проголосовану відповідь.
  • Створено за допомогою JSBench.me на Google Chrome 57.

Порівняння рішень


@Green: це так , ви впевнені, що ви вказали селектор двома двокрапками?
Пшемек

1
Ви фактично не хочете використовувати знак плюс (+) як метод конкатенації в ES6. Ви хочете використовувати літеральні
Стерлінг Борн,

42

Існує дуже простий спосіб здійснити його шляхом заміни . Для ECMAScript 6:

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

Результат:

'Foo'

1
Найкраща відповідь на сьогоднішній день та додаткові бали за показ синтаксису лямбда-регексу. Особливо мені подобається цей, оскільки він може вільно різати і вставляти будь-де.
Уейд Хатлер

Використання /^[a-z]/iбуде краще, ніж використання, .оскільки попередній не намагатиметься замінити будь-який символ, крім алфавітів
Code Maniac

38

У CSS це здається легше:

<style type="text/css">
    p.capitalize {text-transform:capitalize;}
</style>
<p class="capitalize">This is some text.</p>

Це з властивості перетворення тексту CSSW3Schools ).


28
@Simon Не вказано, що рядок обов'язково буде виводитися як частина документа HTML - CSS буде корисний лише тоді, коли він є.
Адам Хептон

9
Адам, правда, але я здогадуюсь, що понад 95% Javascript там використовується з HTML та CSS. На жаль, заява "з великої літери" насправді складається з великої літери кожного слова , тому вам все одно знадобиться JS, щоб використовувати великі літери лише першу літеру рядка.
Саймон Схід

18
Неправильно, Дінеш. Він сказав перший символ струни .
Саймон Схід

81
Ця відповідь, незважаючи на смішну кількість відгуків, є просто неправильною, оскільки вона буде використовувати великі літери першої літери кожного слова. @Ryan, ви отримаєте дисциплінований знак, якщо видалите його. Будь ласка, зробіть це.
Дан Даскалеску

10
Погодьтеся з @DanDascalescu - відповідь Райана абсолютно неправильна.
Тимо


38

Я не бачив жодної згадки в існуючих відповідях на питання, пов'язані з кодовими астральними площинами або інтернаціоналізацією. "Прописні літери" не означають однакову річ у кожній мові з використанням заданого сценарію.

Спочатку я не бачив жодної відповіді, що стосувалася б питань, пов’язаних з кодовими точками астральної площини. Є такий , але він трохи закопаний (як, напевно, буде цей!)


Більшість запропонованих функцій виглядають так:

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

Однак деякі випадкові символи знаходяться поза BMP (основна багатомовна площина, кодові точки U + 0 до U + FFFF). Наприклад, візьміть цей текст Deseret:

capitalizeFirstLetter("𐐶𐐲𐑌𐐼𐐲𐑉"); // "𐐶𐐲𐑌𐐼𐐲𐑉"

Перший символ тут не дає великої літери, оскільки властивості, індексовані масивом рядків, не мають доступу до "символів" або кодових точок *. Вони отримують доступ до кодових одиниць UTF-16. Це справедливо і під час нарізки - значення індексу вказують на кодові одиниці.

Буває так, що кодові одиниці UTF-16 дорівнюють 1: 1 з кодовими точками USV в двох діапазонах, U + 0 до U + D7FF і U + E000 до U + FFFF включно. Більшість випадкових персонажів потрапляють у ці два діапазони, але не всі вони.

З ES2015 року впоратися з цим стало трохи простіше. String.prototype[@@iterator]дає рядки, що відповідають кодовим точкам **. Наприклад, ми можемо це зробити:

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

capitalizeFirstLetter("𐐶𐐲𐑌𐐼𐐲𐑉") // "𐐎𐐲𐑌𐐼𐐲𐑉"

Для довших рядків це, мабуть, не дуже ефективно *** - нам не потрібно повторювати залишок. Ми могли би скористатися String.prototype.codePointAtтим першим (можливим) листом, але нам все-таки потрібно визначити, звідки повинен починатися фрагмент. Одним із способів уникнути повторення залишку було б перевірити, чи є перша кодова точка поза BMP; якщо це не так, фрагмент починається з 1, а якщо він є, то зріз починається з 2.

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

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

capitalizeFirstLetter("𐐶𐐲𐑌𐐼𐐲𐑉") // "𐐎𐐲𐑌𐐼𐐲𐑉"

Ви можете використати побітну математику замість > 0xFFFFцього, але, мабуть, простіше зрозуміти цей спосіб, і ви домоглись того ж самого.

Ми також можемо зробити цю роботу в ES5 і нижче, якщо за необхідності трохи поглибити цю логіку. В ES5 немає внутрішніх методів роботи з кодовими точками, тому ми повинні вручну перевірити, чи є першою кодовою одиницею сурогат ****:

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("𐐶𐐲𐑌𐐼𐐲𐑉") // "𐐎𐐲𐑌𐐼𐐲𐑉"

На початку я також зазначив міркування щодо інтернаціоналізації. Деякі з них дуже важко пояснити, оскільки вони вимагають знання не тільки того, якою мовою користуються, але також можуть вимагати конкретних знань про слова в мові. Наприклад, ірландський диграф "mb" з великої літери починається із слова "mB" на початку слова. Інший приклад, німецький ессет, ніколи не починає слова (afaik), але все ж допомагає проілюструвати проблему. Ессет з нижнього регістру ("ß") з великої літери складається з "SS", але "SS" може бути з малих літер до "ß" або "ss" - для знань, що це правильно, вам потрібні позамовні знання німецької мови!

Найвідоміший приклад подібних питань, мабуть, - турецька. У турецькій латині основною формою i є İ, тоді як нижча форма I - ı - це дві різні літери. На щастя, у нас є спосіб пояснити це:

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

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

У веб-переглядачі найпопулярніший мовний тег користувача вказується на navigator.language, список у порядку вподобань знаходиться на navigator.languages, і мова даного елемента DOM може бути отримана (як правило) за допомогою Object(element.closest('[lang]')).lang || YOUR_DEFAULT_HEREбагатомовних документів.

В агентах, які підтримують класи символів властивостей Unicode в RegExp, які були представлені в ES2018, ми можемо додатково очистити речі, прямо висловивши, які символи нас цікавлять:

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

Це може бути налаштовано трохи, щоб також обробляти великі слова в рядку з досить хорошою точністю. CWUАбо Changes_When_Uppercased властивість символів відповідає всім точкам коду , які, ну, коли зміни в верхньому регістрі. Ми можемо спробувати це за допомогою заголовків диграфних символів, таких як голландський ij, наприклад:

capitalizeFirstLetter('ijsselmeer'); // "IJsselmeer"

На момент написання (лютий 2020 року) Firefox / Spidermonkey ще не застосував жодної з функцій RegExp, впроваджених за останні два роки *****. Ви можете перевірити поточний стан цієї функції в таблиці співзвуччя Kangax . Babel вміє компілювати літерали RegExp з посиланнями на властивості до еквівалентних шаблонів без них, але пам’ятайте, що отриманий код може бути величезним.


Ймовірно, люди, які задають це питання, не будуть стосуватися десеретської капіталізації чи інтернаціоналізації. Але добре бути в курсі цих питань, тому що є хороший шанс, що ви зіткнетесь з ними в підсумку, навіть якщо вони зараз не стосуються. Вони не є "крайніми" випадками, а точніше, вони не за визначенням крайових випадків - є ціла країна, де більшість людей розмовляють турецькою, так чи інакше, і поєднання кодових одиниць з кодовими точками є досить поширеним джерелом помилок (особливо з стосовно емоджи). І рядки, і мова досить складні!


* Кодові одиниці UTF-16 / UCS2 також є кодовими точками Unicode в тому сенсі, що, наприклад, U + D800 технічно є кодовою точкою, але це не те, що це "означає" тут ... начебто ... хоча це стає досить нечіткий. Однак сурогати, безумовно, не є USV (скалярні значення Unicode).

** Хоча якщо блок сурогатного коду є "сиротою" - тобто не є частиною логічної пари - ви все одно можете отримати сюрогати і тут.

*** можливо. Я цього не перевіряв. Якщо ви не визначили, що використання великих літер є вагомим вузьким місцем, я, мабуть, не став би це - вибирайте те, що ви вважаєте, найбільш зрозумілим і читабельним.

**** така функція, можливо, хотіла б протестувати як перший, так і другий кодові одиниці замість лише першого, оскільки можливо, що перший підрозділ є сиротом сурогатом. Наприклад, вхід "\ uD800x" буде використовувати великі букви X як є, чого можна або не очікувати.

***** Ось проблема Bugzilla, якщо ви хочете більше слідкувати за прогресом.


2
Цю відповідь потрібно перемістити на фронт.
Рунар Берг

Дякую @ RúnarBerg - оскільки ваш коментар нагадав мені про це, я прочитав його ще раз і зрозумів, що залишив остаточну справу та рішення, яке варто згадати. Також спробували краще уточнити деякі термінології.
напівколонка

Чудова відповідь .....
Бен Астон

Ця відповідь є чудовою, я б хотів, щоб я її більше підтримував.
Девід Баркер

37

Завжди краще обробляти ці речі за допомогою CSS спочатку , загалом, якщо ви можете вирішити щось за допомогою CSS, перейдіть до цього спочатку, а потім спробуйте JavaScript, щоб вирішити свої проблеми, тому в цьому випадку спробуйте використовувати :first-letterв CSS і застосуватиtext-transform:capitalize;

Тому спробуйте створити для цього клас, щоб ви могли використовувати його у всьому світі, наприклад: .first-letter-uppercaseі додайте щось подібне нижче до свого CSS:

.first-letter-uppercase:first-letter {
    text-transform:capitalize;
}

Також альтернативний варіант - JavaScript, тому найкращим буде щось подібне:

function capitalizeTxt(txt) {
  return txt.charAt(0).toUpperCase() + txt.slice(1); //or if you want lowercase the rest txt.slice(1).toLowerCase();
}

і називати це так:

capitalizeTxt('this is a test'); // return 'This is a test'
capitalizeTxt('the Eiffel Tower'); // return 'The Eiffel Tower'
capitalizeTxt('/index.html');  // return '/index.html'
capitalizeTxt('alireza');  // return 'Alireza'

Якщо ви хочете повторно використовувати його знову і знову, краще приєднати його до рідної версії javascript, тому щось подібне нижче:

String.prototype.capitalizeTxt = String.prototype.capitalizeTxt || function() {
    return this.charAt(0).toUpperCase() + this.slice(1);
}

і зателефонуйте як нижче:

'this is a test'.capitalizeTxt(); // return 'This is a test'
'the Eiffel Tower'.capitalizeTxt(); // return 'The Eiffel Tower'
'/index.html'.capitalizeTxt();  // return '/index.html'
'alireza'.capitalizeTxt();  // return 'Alireza'

36

Якщо ви хочете переформатувати текст з великої літери, ви можете змінити інші приклади як такі:

function capitalize (text) {
    return text.charAt(0).toUpperCase() + text.slice(1).toLowerCase();
}

Це забезпечить зміну наступного тексту:

TEST => Test
This Is A TeST => This is a test

Напевно, варто відзначити, що це також перетворить такі речі, як абревіатури, у малі регістри, тому, можливо, не найкраща ідея в більшості випадків
монокром

Крім того, чи GAMITG дійсно зробив редагування лише для того, щоб видалити фрагмент пробілу з некодової частини публікації? О_О
monokrome

btw, це порушить великі абревіатури, тому будьте обережніші <3
monokrome

34
function capitalize(s) {
    // returns the first letter capitalized + the string from index 1 and out aka. the rest of the string
    return s[0].toUpperCase() + s.substr(1);
}


// examples
capitalize('this is a test');
=> 'This is a test'

capitalize('the Eiffel Tower');
=> 'The Eiffel Tower'

capitalize('/index.html');
=> '/index.html'

Готово @Ram. Також включені приклади.
Фредрік А.


1
Це не @DanDascalescu. Я гадаю, ви можете стверджувати, що substr/ substringє трохи більш семантичним на відміну від slice, але це лише питання переваги. Проте я включив приклади з рядками, наведеними у запитанні, що є приємним штрихом у прикладі '09. Я чесно думаю, що це зводить мене до 15-річного віку, який хоче карми на StackOverflow;)
Фредрік А.

34

Ось функція, яка називається ucfirst () (скорочення " великої літери першої літери"):

function ucfirst(str) {
    var firstLetter = str.substr(0, 1);
    return firstLetter.toUpperCase() + str.substr(1);
}

Ви можете використовувати великі літери, зателефонувавши ucfirst ("деяка рядок") - наприклад,

ucfirst("this is a test") --> "This is a test"

Це працює, розділивши струну на дві частини. У першому рядку він витягує firstLetter, а потім на другому рядку використовує великі літери firstLetter , викликаючи firstLetter.toUpperCase () і з'єднує його з рештою рядка, що знаходиться за допомогою виклику str.substr (1) .

Ви можете подумати, що це не зможе отримати порожній рядок, і справді на такій мові, як C, вам доведеться це задовольнити. Однак у JavaScript, коли ви берете підрядку порожнього рядка, ви просто повернете порожній рядок.


4
Використовуйте String.substring () або String.slice () ... Не використовуйте substr () - застаріле.
Джеймс

7
@ 999: де йдеться про substr()застаріле? Це навіть не зараз, через три роки, не кажучи вже у 2009 році, коли ви зробили цей коментар.
Дан Даскалеску

substr()може не бути позначено як застаріле будь-якою популярною реалізацією ECMAScript (я сумніваюся, що вона не зникне незабаром), але це не є частиною специфікації ECMAScript. У 3-му виданні специфікації згадується це у ненормативному додатку, щоб "запропонувати єдину семантику таких властивостей, не роблячи властивості або їх семантику частиною цього стандарту".
Пітер Руст

2
Маючи 3 методи , які роблять те ж саме ( substring, substrі slice) занадто багато, ІМО. Я завжди використовую, sliceоскільки він підтримує негативні індекси, він не має заплутаної поведінки заміни аргументів, а його API схожий з sliceіншими мовами.
Петро Руст

29
String.prototype.capitalize = function(){
    return this.replace( /(^|\s)([a-z])/g , function(m,p1,p2){ return p1+p2.toUpperCase();
    } );
};

Використання:

capitalizedString = someString.capitalize();

Це текстовий рядок => Це текстовий рядок


20
Регулярні вирази для цього є надмірними.
Ентоні Сотиль

+1, це те, що я справді шукав. Однак є незначна помилка, вона повинна бути return.this.toLocaleLowerCase().replace(...
tomdemuyt

+1, я знайшов цю сторінку, яка шукає версію javascript phps ucfirst, і я підозрюю, що більшість людей її знаходять.
Benubird

@DanDascalescu Я вважаю це корисним, тому +1 утилітаризм та -1 анальна затримка. Він включив приклад, тому його функція зрозуміла.
Тревіс Вебб

String.prototype.capitalize = function(){ return this.replace( /(^|\s)[a-z]/g , function(m){ return m.toUpperCase(); }); }; Я трохи перефактуюю ваш код, вам потрібна лише перша відповідність.
ІГРАЧ

28
var str = "test string";
str = str.substring(0,1).toUpperCase() + str.substring(1);

21

Оформити замовлення на це рішення:

var stringVal = 'master';
stringVal.replace(/^./, stringVal[0].toUpperCase()); // returns Master 

3
Це має бути прийнятою відповіддю. Основне рішення не повинно використовувати рамку, як підкреслення.
Адам Макартур

3
Збережіть кілька натискань клавіш;)stringVal.replace(/^./, stringVal[0].toUpperCase());
Альфредо Дельгадо

1
Регекс не слід застосовувати там, де це не потрібно. Це вкрай неефективно, і він не робить код більш стислим. Більше того, stringVal[0]було б undefinedпорожнім stringVal, і як така спроба доступу до власності .toUpperCase()призвела б до помилки.
Пшемек

20
yourString.replace(/^[a-z]/, function(m){ return m.toUpperCase() });

(Ви можете інкапсулювати його у функції або навіть додати його до прототипу String, якщо ви часто використовуєте його.)


5
Незважаючи на те, що за це є досить багато голосів, це, безумовно, найбільш повільне рішення, розміщене тут. Я зібрав невеличку швидкість з найпопулярнішими відповідями з цього повідомлення, тут: forwebonly.com/…
Робін ван Бален

@RobinvanBaalen Ваше посилання зараз розірвано. Отримали оновлений?
Бред

1
Regexp є надмірним для цього, віддайте перевагу більш простому: str.charAt (0) .toUpperCase () + str.slice (1)
Саймон

@Brad на жаль ні
Робін ван Бален

Часто, якщо ви хочете вирішити свою проблему за допомогою регулярного вираження, ви стикаєтесь з двома проблемами.
Пшемек

19

ucfirstФункція працює , якщо ви робите це так.

function ucfirst(str) {
    var firstLetter = str.slice(0,1);
    return firstLetter.toUpperCase() + str.substring(1);
}

Дякую JP за розголос.


2
приємна назва функції! Його ім’я є ідентичним еквіваленту PHP Насправді є ціла бібліотека функцій PHP, написана в JS; Він називається PHP.js, і його можна знайти на http://phpjs.org
Хусам

11
Один лайнер:string[0].toUpperCase() + string.substring(1)
dr.dimitru

@TarranJones тут куленепробивний один вкладиш:(string[0] || '').toUpperCase() + string.substring(1)
dr.dimitru

@ dr.dimitru: Замість ідіоматичного (string[0] || '')ви могли просто string.charAt(0).
Пшемек


17
yourString.replace(/\w/, c => c.toUpperCase())

Я знайшов цю функцію стрілки найпростішою. Замінити відповідає першому символу ( \w) букви вашої рядка та перетворить його у великі регістри. Нічого фантазії не потрібно.


1
Це має бути прийнятою відповіддю, натомість це майже остання, оскільки SO продовжує видавати застарілі запитання. До речі, краще скористатися /./з двох причин: /\w/буде пропущено всі попередні символи без букви (так @@ abc стане @@ Abc), а потім це не працюватиме з не латинськими символами
Крістіан Трайна
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.