当前位置:首页 > 物理机 > 正文

JS如何获取数组长度和字符串长度?,有哪些方法

js获取数组长度和获取字符串长度,核心都是用length属性,但两者的细节坑完全不同。本文从底层原理、实操代码、性能优化三个维度拆解,帮你彻底拿捏数组和字符串的长度获取。

js数组长度怎么获取:length属性详解

在JavaScript中,数组的长度获取方式非常直接:arr.length,这个属性返回的是数组元素的数量,注意它不一定是数组中实际存在的元素个数,而是数组最大索引加1

length属性的底层逻辑

数组的length属性并不是实时遍历计算出来的,它更像一个“计数器”,始终维护在内存中,当你往数组里添加或删除元素时,length会自动更新,但有几个边界情况需要留意。

第一,稀疏数组的长度计算。 如果你这样写:

const arr = [1, , 3]; // 中间是空槽位 console.log(arr.length); // 输出 3

数组中间的空位仍然会被计入length,这在遍历时会带来意想不到的麻烦,比如forEach会跳过空槽位,但map会保留空槽位,关于稀疏数组的细节,你可以调用arr.hasOwnProperty(1)来验证这个位置是否存在。

第二,length属性是可写的。 这是数组长度和字符串长度最大的区别,字符串的length是只读的,但数组的length可以主动赋值,赋值会反向影响数组内容:

const list = [1, 2, 3, 4, 5]; list.length = 3; console.log(list); // [1, 2, 3],后面两个元素直接被截断了

这个特性在清空数组时非常好用,arr.length = 0一步到位,比splice(0, arr.length)的性能更好,业内专家指出,在V8引擎的优化下,直接修改length属性是清空数组的最优解之一。

第三,类数组对象的情况。 在DOM操作中比较常见的是arguments对象或者NodeList,它们虽然有length属性,但并不是真正的数组,如果你想用数组的方法处理它们,需要先转换:

const divs = document.querySelectorAll('div'); console.log(divs.length); // 这里能正常获取长度 // 但 divs.push() 会报错,因为NodeList没有push方法

实战:前端开发中数组长度获取的性能优化

在前端的循环场景中,如果不注意length的读取方式,会带来不必要的性能开销。

// 不推荐:每次循环都读取一次length for (let i = 0; i < arr.length; i++) { // 执行逻辑 } // 推荐:缓存length值 for (let i = 0, len = arr.length; i < len; i++) { // 执行逻辑 }

当数组规模较小时,这种差异微乎其微,但在处理大量数据时(比如上万条记录),缓存length能减少属性的查找开销,统计数据显示,多数情况下这种方法在二手设备或低端手机上能带来肉眼可见的流畅度提升。

length和size容易混淆吗:js中的对比

很多从jQuery转过来的开发者,会下意识地写$(arr).size(),实际上size()在jQuery 3.0版本中已经被移除了,官方推荐直接用$().length,在原生JavaScript中,只有length,没有size方法。

JavaScript中的length图谱

数据类型 获取长度方式 是否只读
数组 arr.length 可写
字符串 str.length 只读
函数 fn.length(返回形参个数) 只读
arguments对象 arguments.length 只读
Map/Set map.size / set.size 只读

从表格能看出来,只有数组的length是特殊的,Map和Set用的是size属性,这也是很多初学者混淆的地方,如果你在开发中遇到map.length返回undefined,不用怀疑,你应该用map.size。

js中获取数组长度的常见误区

把字符串的length带进数组的操作里。 比如想把字符串按字符切割成数组再去数个数,多此一举。

以为数组的length等于元素个数。 在不含空槽位的连续数组中,length确实等于元素个数,但一旦你删除了中间某个元素:

JS如何获取数组长度和字符串长度?,有哪些方法 第1张

这里delete操作没有改变length,数组变成了[1, empty, 3],正确方式是使用splice,它才真正改变了数组的长度。

js获取字符串长度:不同场景下的正确姿势

str.length是获取字符串长度的标准方式,它返回的是UTF-16编码单元的数量,看到这里你可能已经意识到问题:中文和特殊字符的情况没那么简单。

基础用法与字符编码问题

先看一个让人困惑的例子:

const str = 'hello'; console.log(str.length); // 5 const cnStr = '你好'; console.log(cnStr.length); // 2,中文按一个字符计算 const emoji = ''; console.log(emoji.length); // 2,因为emoji是代理对

为什么emoji是2? 因为JavaScript内部使用UTF-16编码,大部分常用字符(包括中文)占1个编码单元,而emoji和某些生僻字占了2个编码单元,这类字符属于“代理对”。

js获取字符串长度的方法与Unicode处理

如果你想按用户可感知的“字符数”来获取长度,比如限制用户输入的最大字数,直接用str.length就可能出问题,正确的处理方式有几种:

// 方式一:使用Array.from const emoji = ''; console.log(Array.from(emoji).length); // 1 // 方式二:使用扩展运算符 console.log([...emoji].length); // 1 // 方式三:使用Intl.Segmenter(现代浏览器) // 处理带表情组合的更复杂情况 const segmenter = new Intl.Segmenter('zh', { granularity: 'grapheme' }); const segments = [...segmenter.segment('‍‍‍')]; console.log(segments.length); // 1,完整家庭emoji算一个字符

技术方案的取舍: 方式一和方式二在绝大多数场景够用,且代码简洁,方式三的Intl.Segmenter更精确,但浏览器兼容性要求高一些,行业共识认为在处理用户输入的字符计数时,采用Array.from的方案是性价比最高的折中。

获取字符串长度按字节算的场景

某些场景下需要计算字符串的字节长度,比如后端接口对数据大小有严格限制,这时候有一个经典算法:

function getBytesLength(str) { let bytes = 0; for (let i = 0; i < str.length; i++) { const codePoint = str.codePointAt(i); if (codePoint > 255) { bytes += 2; i++; // 跳过代理对的第二个单元 } else { bytes += 1; } } return bytes; }

或者更简洁的写法:

const utf8Length = new TextEncoder().encode(str).length;

TextEncoder是现代浏览器和Node.js的原生API,性能表现稳定,比手写循环更可靠,它返回的是UTF-8编码后的字节数,中文字符会被计算为3字节。

JS如何获取数组长度和字符串长度?,有哪些方法 第2张

js字符串转数组后长度对比

在项目实战中,处理用户输入时(比如微博风格的字符计数),用str.length和用Array.from(str).length的结果会根据内容的不一样有差异,包含emoji的输入,两者数据就会对不上,前端开发中的字符计数,建议统一使用[...str].length。

如果还想更严谨地处理组合字符(比如表情加上肤色修饰符),那就只能上Intl.Segmenter了。

js获取数组长度和字符串长度的应用场景剖析

数组长度在表格分页中的应用

实际项目中,数组长度最常见的使用场景就是前端分页和表格筛选,比如要计算总页数:

const totalPages = Math.ceil(totalItems.length / pageSize);

这里有一个隐藏的边界问题:如果数据源是动态加载的接口返回,你可能拿到的是一个类数组对象而不是纯数组,此时稳妥的做法是先转换再求长度:

const data = Array.from(response.data); const total = data.length;

数据更新前的校验逻辑

在表单提交前,对多选列表的长度校验也是刚需场景:

const selectedItems = []; function validateSelection() { if (selectedItems.length === 0) { // 提示用户至少选择一项 } }

关于js获取数组长度和字符串长度的常见问题解答

问:数组length设为0和重新赋值空数组,哪种清空方式更推荐?

答: 如果原数组还在被其他地方引用,那必须用arr.length = 0,因为重新赋值arr = []会创建新的数组对象,原来的引用指向的内容没变,容易造成内存泄漏,如果没有其他引用,两者皆可。

问:在Vue或React中,获取字符串长度有没有特殊注意事项?

答: 框架层面没有特殊限制,但需要注意响应式机制,在Vue 3中,Array.from(str)返回的新数组不会触发响应式依赖,所以如果要在计算属性里根据字符串长度派生数据,直接在computed里写str.value.length即可,不需要额外的包装。

问:为什么数组的length值可以直接修改,而字符串的不行?

答: 数组和字符串在JavaScript中是两种不同的数据结构,数组是可变对象,length属性的修改是规范明确规定的行为,用来支持截断和扩展操作,字符串是原始类型(primitive type),不可变是它的核心特性,每次修改字符串都会创建新值,所以length天然只读,前端开发中要避开一个常见的隐式错误,就是尝试用str.length = 1来截断字符串,这种写法静默失效,没有任何效果。


数组的length和字符串的length,名字相同,但性格完全不同,数组版是可变、可写、带副作用的,字符串版是只读、稳定、不可变更的,理解了这个底层差异,你在实际开发中就能少踩很多坑,遇到字符计数拿不准的时候,回头想想UTF-16和组合字符,用Array.from做兜底,方案不会有错。

0