为何for...of遍历数组时原数组未更新?两类titleCase函数差异解析
为什么
titleCase1无法更新数组,而titleCase2可以? 核心原因很简单:for...of循环里的word是数组元素的副本,不是对原数组元素的引用,而for循环通过索引直接操作数组元素,所以能修改原数组。
咱们一步步拆解:
先看titleCase1的问题
function titleCase1(str) { let words = str.split(" "); for (let word of words) { // 这里的word是数组当前元素的"拷贝" word = word[0].toUpperCase() + word.slice(1); } return words.join(" "); }
当你用for (let word of words)遍历数组时,每次循环的word变量都会拿到当前数组元素的值副本——因为字符串是JavaScript里的值类型,传递的时候是复制值而不是引用。
你在循环里给word赋值,只是改变了这个临时变量的内容,完全不会影响原数组words里的元素。循环结束后,words数组还是原来的样子,所以最后join出来的自然还是原字符串。
再看titleCase2为什么生效
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[i]直接指向数组在索引i位置的元素。当你给words[i]赋值时,是直接修改了数组本身对应的位置,所以循环结束后,words数组里的每个元素都被更新成了首字母大写的版本,最后join自然能得到正确结果。
举个更直观的例子
let arr = ['apple', 'banana']; // for...of遍历,修改临时变量,原数组不变 for (let item of arr) { item = item.toUpperCase(); } console.log(arr); // 输出: ['apple', 'banana'] // 索引遍历,直接修改数组元素,原数组改变 for (let i = 0; i < arr.length; i++) { arr[i] = arr[i].toUpperCase(); } console.log(arr); // 输出: ['APPLE', 'BANANA']
补充:如果是引用类型会怎样?
要是数组里存的是对象(引用类型),for...of里修改对象的属性是会影响原数组的,因为此时word拿到的是对象的引用。比如:
let arr = [{name: 'alice'}, {name: 'bob'}]; for (let obj of arr) { obj.name = obj.name.toUpperCase(); } console.log(arr); // 输出: [{name: 'ALICE'}, {name: 'BOB'}]
但你的例子里是字符串(值类型),所以不存在这种情况~
内容的提问来源于stack exchange,提问作者Atavachron
相关产品推荐
相关产品推荐

