【问题标题】:Can not update first character of a string - Javascript无法更新字符串的第一个字符 - Javascript
【发布时间】:2018-02-01 19:53:37
【问题描述】:

我有以下代码应该将每个单词的第一个字母大写。但是第一个字符 arr[i][0] 没有得到更新。我最终做了 arr[i] = arr[i][0].toUpperCase() + arr[i].substr(1) ,但我不明白为什么下面的方法不起作用。

function titleCase(string) {
  const arr = string.split(' ');
  for (let i = 0; i < arr.length; i++){
    arr[i][0] = arr[i][0].toUpperCase();
  }
  return arr.join(' ');
}

【问题讨论】:

  • 字符串是不可变的,但你可以拆分字符串并加入它,现在使用切片。

标签: javascript string uppercase


【解决方案1】:

因为字符串在 JavaScript 中是不可变的,这意味着您无法更改它们。每次您尝试修改字符串时,您实际上是在创建一个包含更改的新字符串。

所以当您执行arr[i][0] 时,它不是对第一个字符的引用,而是对第一个字符的副本的引用。而且由于您没有保留该引用(即通过将其分配给变量),因此它丢失了。

您修复它的方式arr[i] = arr[i][0].toUpperCase() + arr[i].substr(1) 是一种好方法。

【讨论】:

    【解决方案2】:

    function titleCase(string) {
      const arr = string.split(' ');
    
      for (let i = 0; i < arr.length; i++) {
      
        // arr[i] is a String!!!
        const word = arr[i];
        
        // now, in order to target and mutate the [0]th key we need an Array:
        let charsArray = word.split("");
        
        // Now you can do .toUpperCase() on the [0]th array key
        charsArray[0] = charsArray[0].toUpperCase();
        
        // Convert Array to string and update arr[i]
        arr[i] = charsArray.join("");
    
      }
      return arr.join(' ');
    }
    
    console.log( titleCase("hello world") )

    或者你可以simply use String.prototype.replace()MDN

    const titleCase = str => str.replace(/\b(\w)/g, f => f.toUpperCase());
    
    console.log( titleCase("hello world") )

    【讨论】:

      【解决方案3】:

      正如另外指出的,字符串在 JavaScript 中是不可变的,这意味着你不能改变它们的值。如果要将字符串的第一个字母变为大写,则必须构造一个 new 字符串

      str[0].toUpperCase() + str.slice(1)
      

      或者更一般地说,如果我们在特定索引处使用大写字母,i

      str.slice(0,i) + str[i].toUpperCase() + str.slice(i + 1)
      

      我们可以创建一个函数toUpperCaseAt,它接受一个字符串和一个索引并为我们执行这个操作。

      const toUpperCaseAt = (str = "", i = 0) =>
        i >= str.length
          ? str
          : str.slice (0, i) + str [i] .toUpperCase () + str.slice (i + 1)
      

      接下来,我们编写一个简单的递归函数titleCase,逐个遍历字符串。

      • 基本情况:索引超出范围 - 返回输入字符串
      • 归纳案例 1:索引未超出范围且索引为 0 - 第一个字母应始终大写
      • 归纳案例 2:索引不是越界,不是 0,并且索引当前引用一个空格字符 - 下一个字母大写
      • 归纳案例 3:索引没有越界,不是 0,也不是空格 - 前进到下一个索引

      这个答案不需要依赖像String.prototype.splitArray.prototype.join这样的高级内置函数——而是向您展示如何使用您自己创建的简单函数来实现结果。

      const titleCase = (str = "", i = 0) =>
        i >= str.length
          ? str
          : i === 0
            ? titleCase (toUpperCaseAt (str, i), 1)
            : str [i] === " "
              ? titleCase (toUpperCaseAt (str, i + 1), i + 1)
              : titleCase (str, i + 1)
      
      console.log (titleCase ('hello, my name is me.'))
      // Hello, My Name Is Me.
      

      如果我们不确定它是如何工作的,我们甚至可以删除 String.prototype.slice 依赖项

      const slice = (str = "", from = 0, to = str.length) =>
        from >= to
          ? ''
          : str [from] + slice (str, from + 1, to)
      

      现在整件事在一起

      const slice = (str = "", from = 0, to = str.length) =>
        from >= to
          ? ""
          : str [from] + slice (str, from + 1, to)
      
      const toUpperCaseAt = (str = "", i = 0) =>
        i >= str.length
          ? str
          : slice (str, 0, i) + str [i] .toUpperCase () + slice (str, i + 1)
      
      const titleCase = (str = "", i = 0) =>
        i >= str.length
          ? str
          : i === 0
            ? titleCase (toUpperCaseAt (str, i), 1)
            : str [i] === " "
              ? titleCase (toUpperCaseAt (str, i + 1), i + 1)
              : titleCase (str, i + 1)
              
      console.log (titleCase ('hello, my name is me.'))
      // Hello, My Name Is Me.

      【讨论】:

        猜你喜欢
        • 2011-06-01
        • 2019-11-29
        • 2015-12-14
        • 2021-04-29
        • 1970-01-01
        • 2023-04-07
        • 2017-08-23
        • 1970-01-01
        • 2016-05-09
        相关资源
        最近更新 更多