JavaScript对象数组字段中查找字符串失败问题排查
问题分析:字符串匹配失败及长度差异原因
问题场景
- 手动定义目标字符串:
city = 'Hải Phòng' - 通过API获取的数组(接口地址:
https://donhang.vnpost.vn/api/api/TinhThanh/GetAll):data = [{},{},{},{ MaTinhThanh: 'xx', TenTinhThanh: 'Hải Phòng' },{},{}] - 用于查找目标对象的代码:
mycity = data.find(c => c.TenTinhThanh.includes(city)) - 实际返回结果:
undefined,预期结果:{ MaTinhThanh: 'xx', TenTinhThanh: 'Hải Phòng' } - 关键异常:两个视觉完全一致的字符串长度不同
data[3].TenTinhThanh.length // 结果为11 city.length // 结果为9
问题根源
这是Unicode字符的规范化形式差异导致的:
- 你手动编写的
'Hải Phòng'里,带声调的字符(比如ạ、ộ)是预组合字符——每个字符对应单个Unicode码点(例如ạ对应U+1EA1,ộ对应U+1ED3),所以整个字符串总长度为9。 - API返回的字符串中,这些带声调的字符是分解形式——由基础字母+独立的声调符号组合而成(例如
ạ是a+重音符+低平声调,共3个码点;ộ是o+重音符+高降声调,共3个码点),额外的声调符号占用了码点,导致总长度变为11。 - 视觉上两个字符串完全相同,但底层编码不一致,因此
includes方法无法匹配成功。
解决方法
使用JavaScript的String.prototype.normalize()方法,将两个字符串统一为相同的规范化形式(推荐使用NFC,即预组合形式)后再进行匹配:
方案1:包含匹配(适用于模糊场景)
const normalizedCity = city.normalize('NFC'); mycity = data.find(c => c.TenTinhThanh?.normalize('NFC').includes(normalizedCity));
方案2:严格相等匹配(适用于精确匹配地名)
const normalizedCity = city.normalize('NFC'); mycity = data.find(c => c.TenTinhThanh?.normalize('NFC') === normalizedCity);
注:代码中的?.是可选链操作符,用于防止数组中存在空对象时触发Cannot read properties of undefined错误。
内容的提问来源于stack exchange,提问作者JackForez
相关产品推荐
相关产品推荐

