【问题标题】:Capitalize the first letter of each word将每个单词的首字母大写
【发布时间】:2015-11-10 17:59:19
【问题描述】:
var name = "AlbERt EINstEiN";

function nameChanger(oldName) {
var finalName = oldName;
// Your code goes here!
finalName = oldName.toLowerCase();

finalName = finalName.replace(finalName.charAt(0), finalName.charAt(0).toUpperCase());

for(i = 0; i < finalName.length; i++) {
    if (finalName.charAt(i) === " ")
        finalName.replace(finalName.charAt(i+1), finalName.charAt(i+1).toUpperCase());
}


// Don't delete this line!
return finalName;
};

// Did your code work? The line below will tell you!
console.log(nameChanger(name));

我的代码原样返回“阿尔伯特·爱因斯坦”。我想知道我哪里出错了? 如果我添加

console.log(finalName.charAt(i+1));

在 if 语句之后,并注释掉其余部分,它会打印“e”,因此它会像它应该的那样识别 charAt(i+1)...我只是无法让它将第二个单词的第一个字母大写。

【问题讨论】:

    标签: javascript string


    【解决方案1】:

    您的代码示例存在两个问题。我会一一介绍。

    字符串是不可变的

    这并不像你想象的那样工作:

    finalName.replace(finalName.charAt(i+1), finalName.charAt(i+1).toUpperCase());
    

    您需要将其更改为:

    finalName = finalName.replace(finalName.charAt(i+1), finalName.charAt(i+1).toUpperCase());
    

    在 JavaScript 中,字符串是不可变的。这意味着一旦创建了字符串,就不能更改它。这听起来可能很奇怪,因为在您的代码中,您似乎正在使用 replace() 之类的方法在整个循环中更改字符串 finalName

    但实际上,您并没有真正改变它! replace() 函数接受一个输入字符串,进行替换,然后生成一个新的输出字符串,因为它实际上不允许更改输入字符串(不变性)。所以,tl;dr,如果你没有通过将replace() 的输出分配给一个变量来捕获它,那么被替换的字符串就会丢失。

    顺便说一句,将它分配回原始变量名是可以的,这就是为什么你可以这样做finalName = finalName.replace(...)


    替换是贪心的

    您会遇到的另一个问题是,当您使用 replace() 时,您将替换字符串中的 所有 匹配字符,而不仅仅是您正在检查的位置的字符.这是因为replace() 是贪婪的 - 如果你告诉它用 'E' 替换 'e',它会替换所有的!

    本质上,您需要做的是:

    1. 找到一个空格字符(你已经这样做了)
    2. 抓取所有字符串,包括空格;字符串的这个“边”很好。
    3. 将下一个字母转换为大写,但只转换那个字母。
    4. 获取字符串的其余部分,过去您转换的字母。
    5. 将所有三个部分放在一起(字符串开头、大写字母、字符串结尾)。

    slice() 方法会做你想做的事:

    if (finalName.charAt(i) === " ") {
        // Get ONLY the letter after the space
        var startLetter = finalName.slice(i+1, i+2);
        // Concatenate the string up to the letter + the letter uppercased + the rest of the string
        finalName = finalName.slice(0, i+1) + startLetter.toUpperCase() + finalName.slice(i+2);
    }
    

    另一个选项是正则表达式(regex),其他答案都提到了。这可能是一个更好的选择,因为它更清洁。但是,如果您是第一次学习编程,通过编写原始循环更容易理解这种手动字符串工作。以后你可以乱用有效的方法来做到这一点。

    工作 jsfiddle:http://jsfiddle.net/9dLw1Lfx/

    进一步阅读:

    【讨论】:

    • ... 因为?你至少应该解释为什么这个改变是必要的,特别是因为这个问题看起来像是家庭作业。
    • 我试过这个,它返回'AlbErt einstein'。不太清楚为什么它会抓住第一个“e”,而不是空格后面的那个?
    • @xdumaine 我同意,当你发表评论时,我正在扩展解释:)
    • 很好的不变性解释!
    • @MartDellon 绝对!乐意效劳。我可以告诉你正在寻找一个基本的解释。我们都曾在这些东西上挣扎过。继续学习!
    【解决方案2】:
    if (finalName.charAt(i) === " ")
    

    不应该

    if (finalName.charAt(i) == " ")
    

    不 === 检查对象类型是否相等,这不应该是因为一个是字符,另一个是字符串。

    【讨论】:

    • 您确定 charAt(i) 返回的是字符串而不是字符吗?
    • 这是以任何方式回答问题。 而且这是错误的,因为 JavaScript 中没有 char 类型,charAt 只返回一个长度为 1 的字符串。
    • CharAt 应该是一个字符,而 " " 应该是一个字符串。但由于是 javascript,不记得 if ' ' == " " 由于弱类型。
    • @JustinChou JavaScript 没有 Char 类型,它使用长度为 1String (或也许2 在某些极端情况下具有不寻常的 USC-16 字符,不确定是否需要阅读规范)
    【解决方案3】:

    如果您将 RegExp /pattern/flags函数 传递给 str.replace 而不是使用子字符串,则可以大大简化此操作

    function nameChanger(oldName) {
        var lowerCase = oldName.toLowerCase(),
            titleCase = lowerCase.replace(/\b./g, function ($0) {return $0.toUpperCase()});
        return titleCase;
    };
    

    在此示例中,我将更改应用于 word boundary \b 之后的任何字符 .,但您可能需要更具体的 /(^| )./g

    【讨论】:

    • 这很神秘,尤其是对于初学者。
    • @xdumaine 具体是哪一部分?我试图通过将其分成三行来使其更清晰。我编辑了一些参考文献
    • 我怀疑 OP 是否会认识到这种替换语法意味着它正在使用正则表达式,更不用说您是如何提出这些正则表达式的或它们的含义了。对于“您的代码在此处”的字符串操作问题,这是相当先进的。
    【解决方案4】:

    这个问题的另一个好答案是使用 RegEx 来为你做这件事。

    var re = /(\b[a-z](?!\s))/g;
    var s = "fort collins, croton-on-hudson, harper's ferry, coeur d'alene, o'fallon"; 
    s = s.replace(re, function(x){return x.toUpperCase();});
    console.log(s); // "Fort Collins, Croton-On-Hudson, Harper's Ferry, Coeur D'Alene, O'Fallon"
    

    所使用的正则表达式可能需要稍微改变一下,但这应该让您了解可以使用正则表达式做什么

    Capitalize Letters with JavaScript

    【讨论】:

      【解决方案5】:

      问题是双重的:

      1) 您需要为 finalName.replace 返回一个值,因为该方法返回一个元素但不会改变它所基于的元素。

      2) 您没有遍历字符串值,因此您只更改了第一个单词。你不想把每个单词都改成小写吗?

      这段代码会更好地为您服务:

         var name = "AlbERt EINstEiN";
      
      function nameChanger(oldName) {
      
          // Your code goes here!
      
          var finalName = [];
          oldName.toLowerCase().split(" ").forEach(function(word) {
              newWord = word.replace(word.charAt(0), word.charAt(0).toUpperCase());
              finalName.push(newWord);
          });
      
      
          // Don't delete this line!
          return finalName.join(" ");
      };
      
          // Did your code work? The line below will tell you!
          console.log(nameChanger(name));
      

      【讨论】:

        猜你喜欢
        • 2020-08-30
        • 2015-11-04
        • 2012-11-11
        • 2012-07-24
        • 2016-12-05
        • 2016-01-10
        • 1970-01-01
        • 2016-12-23
        • 2017-08-02
        相关资源
        最近更新 更多