我编程的方式构建一个URI用的帮助encodeURIComponent
使用用户提供的输入功能。 但是,当用户进入无效的Unicode字符(例如U+DFFF
),该函数将抛出具有以下消息的异常:
的URI将被编码包含无效字符
我看着这件事上MSDN ,但没有告诉我什么我不知道的。
更正此错误
- 确保将被编码字符串中包含唯一有效的Unicode序列。
我的问题是,有没有办法来净化提供的输入删除所有无效的Unicode序列之前,我把它传递给用户encodeURIComponent
的功能?
以方案办法去发现答案,这打开了任何问题的唯一范围为\ ud800- \ udfff,高和低的代理人的范围:
for (var regex = '/[', firstI = null, lastI = null, i = 0; i <= 65535; i++) {
try {
encodeURIComponent(String.fromCharCode(i));
}
catch(e) {
if (firstI !== null) {
if (i === lastI + 1) {
lastI++;
}
else if (firstI === lastI) {
regex += '\\u' + firstI.toString(16);
firstI = lastI = i;
}
else {
regex += '\\u' + firstI.toString(16) + '-' + '\\u' + lastI.toString(16);
firstI = lastI = i;
}
}
else {
firstI = i;
lastI = i;
}
}
}
if (firstI === lastI) {
regex += '\\u' + firstI.toString(16);
}
else {
regex += '\\u' + firstI.toString(16) + '-' + '\\u' + lastI.toString(16);
}
regex += ']/';
alert(regex); // /[\ud800-\udfff]/
然后我用一个简单的例子证实了这一点:
for (var i = 0; i <= 65535 && (i <0xD800 || i >0xDFFF ) ; i++) {
try {
encodeURIComponent(String.fromCharCode(i));
}
catch(e) {
alert(e); // Doesn't alert
}
}
alert('ok!');
而这符合MSDN说什么,因为实际上所有的Unicode字符(甚至是有效的Unicode“非字符”)之外的代理人都是有效的Unicode序列。
事实上,你可以筛选出高和低的代理人,但在高低温对使用时,他们成为合法的(因为他们是为了以这种方式被使用,以允许对Unicode的扩大(大幅)超出字符原来的最大数量):
alert(encodeURIComponent('\uD800\uDC00')); // ok
alert(encodeURIComponent('\uD800')); // not ok
alert(encodeURIComponent('\uDC00')); // not ok either
所以,如果你想采取简单的方法和块代理人,它仅仅是一个的事情:
urlPart = urlPart.replace(/[\ud800-\udfff]/g, '');
如果你想去掉无与伦比(无效)的代理人,同时允许代理对(这是合法的序列,但很少曾经需要的字符),你可以做到以下几点:
function stripUnmatchedSurrogates (str) {
return str.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])/g, '').split('').reverse().join('').replace(/[\uDC00-\uDFFF](?![\uD800-\uDBFF])/g, '').split('').reverse().join('');
}
var urlPart = '\uD801 \uD801\uDC00 \uDC01'
alert(stripUnmatchedSurrogates(urlPart)); // Leaves one valid sequence (representing a single non-BMP character)
如果JavaScript的有负回顾后功能会少了很多丑陋...