使用“数组的元素”进行迭代时,数组未更新

时间:2019-02-09 08:51:58

标签: javascript

我看不到为什么下面的第一个代码(titleCase1)不能大写,而第二个代码却大写(titleCase2)。

var result1 = titleCase1('this is a new question in stackoverflow');
console.log('result1:',result1);

var result2 = titleCase2('this is a new question in stackoverflow');
console.log('result2:',result2);

function titleCase1(str) {
    let words = str.split(" ");
      for (let word of words) {
        word = word[0].toUpperCase() + word.slice(1);
      }
      return words.join(" ");
    }

function titleCase2(str) {
      let words = str.split(" ");
      for (let i = 0; i < words.length; i++) {
        words[i] = words[i][0].toUpperCase() + words[i].slice(1);
      }
      return words.join(" ");
    }

似乎在第一种情况下,words数组未更新,并且与let element of array迭代器有关,但是我不明白为什么它不起作用。

3 个答案:

答案 0 :(得分:1)

  

与JavaScript中的数组不同,字符串是值对象,而不是引用对象。

这里:

for (let word of words) {
    word = word[0].toUpperCase() + word.slice(1);
}

您正在使用let声明一个单词变量,它的作用域为for循环。此变量是字符串中子字符串的副本。您可以在每次迭代时重新分配它,但是由于它是一个副本而不是对子字符串的引用,因此数组words中的子字符串不会更改,只有副本会更改。

但是这里:

for (let i = 0; i < words.length; i++) {
    words[i] = words[i][0].toUpperCase() + words[i].slice(1);
}

您正在直接更改子字符串,因为您是通过在子字符串数组中建立索引来更新每个字符的。

这是使用String.replace,正则表达式和箭头函数的一种更短的方法:

const titleCase = str => str.replace(/(?<=(\s+|^))\w/gi, x => x.toUpperCase());

console.log(titleCase('hello world'));
console.log(titleCase('   hello    world'));

正则表达式(?<=(\s+|^))后面是一个正数,并确保模式\w(单词字符)前面有空格或位于字符串的开头。

答案 1 :(得分:0)

在第一个代码中,您正在重新分配变量。至少在99%的情况下,重新分配变量本身永远不会对其他任何事物产生任何影响;这仅意味着word块中对for的进一步引用将引用新值,而不是旧值。因此,您的word = ...不会有任何影响,因为您稍后在代码块中不会使用新的word变量名进行任何操作。 (在该迭代结束之后,存储在其中的值将被取消引用,并很快将被GC处理)

在第二个代码中,您正在变异一个对象words[i] =意味着对i的索引words的进一步访问将返回新值

答案 2 :(得分:0)

word不是数组。这只是一个字。并且您返回的单词已经加入它们,而这些单词已经是没有空格的字符串,将无效

function titleCase(str) {
let a=[];
let words = str.split("");
  for (let word of words) {
  
    a.push(word.toUpperCase());
  }
  return a.join("");
}
console.log(titleCase("hello"))