JavaScript: 用普通空格替换不间断空格和特殊空格字符

7
我试图调试一个在字符串中搜索的问题,最终发现以下有趣的代码片段。
虽然"item "和"item "看起来相同,但它们实际上并不相等!

var result = ("item " === "item ");

document.write(result);
console.log(result);

进一步通过在 Python 解释器中粘贴它来调查后,我发现第一个 "item " 有一种不同于 "item\xc2\xa0" 的空格。我认为这是一种不间断空格

现在,匹配这些字符串的一个可能的解决方案是用空格替换 \xc2\xa0,但是否有更好的方法将所有特殊空格字符转换为普通空格?


检查两个字符串的"item ".charCodeAt(4)。它们不同。 - adiga
是的,我已经做过了,如问题中所述,字符不同。我的问题是如何比较这些字符串?(不需要修剪/删除空格) - Irshad P I
我只是提到了如何在不使用Python解释器的情况下识别它。 - adiga
你可能想要查看Unicode中可能的空格字符,网址为:https://unicode-table.com/en/search/?q=space,还有一些特定于语言的空格字符。因此,如果你是完美主义者,这可能会变得非常棘手。 - Krisztián Balla
@JennyO'Reilly,哈哈,谢谢。我一定会去看看的。顺便说一下,我的完美主义参数设置为90%。 - Irshad P I
3个回答

8
在 ES2015/ES6 中,您可以使用 String.Prototype.normalize() 方法将两个字符分解为相同的简单空格字符:

const normalize = str => str.normalize('NFKD');
console.log(normalize("item\u0020") === normalize("item\u00a0"));


不支持IE浏览器。 :-D - Krisztián Balla
1
@JennyO'Reilly 是的,IE不支持ES2015的很多功能...但是如果确实需要支持IE,可以尝试使用这个我没有亲测过的polyfil - Kaiido

5
第一个字符串中的空格是字符代码160(不间断空格),而第二个字符串中的空格是字符代码32(普通空格),因此这两个字符串不相等。

console.log("item ".charCodeAt(4), "item ".charCodeAt(4));

有没有更好的方法将所有特殊空格字符转换为普通空格?
您可以匹配不是制表符或换行符的空格字符,并将其替换为普通空格:

const makeSpacesNormal = str => str.replace(/(?=\s)[^\r\n\t]/g, ' ');
console.log(makeSpacesNormal("item ") === makeSpacesNormal("item "));

具体来说,\s将匹配一整串类似于空格的字符

[\t\n\v\f\r \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]

通过匹配和替换字符(除了换行符和制表符,如果你需要的话),你将获得普通空格。


在regex101.com上它说:\s 匹配任何空白字符(等同于 [\r\n\t\f\v ])。那么哪个是错误的? - Krisztián Balla
2
您可以在官方规范此处中查看描述(向上滚动一点,向下滚动 - 查看WhiteSpaceLine Terminator表)。我认为Regex101试图简化所有语言的事情,而不是详细介绍每种语言的机制,不确定它对其他语言有多精确。 - CertainPerformance
我会接受这个答案,因为1. 能够跨浏览器工作,2. 可扩展,3. 详细说明。 - Irshad P I

0

trim会从字符串的开头和结尾删除所有空格。如果您想比较两个字符串并忽略前导和尾随空格,请将它们都修剪(trim)。

"item ".trim() === "item ".trim()

2
但是 OP 想要将所有特殊空格字符转换为普通空格,而不是删除所有前导/尾随空格。 - CertainPerformance
我也想匹配空格。对于 "item" === "item ",它不应该为真。 - Irshad P I

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接