Поскольку этот вопрос первоначально задавался более пяти лет назад, люди все еще неправильно вводят этот тип задачи. Как hippietrail предлагает , ответ медера может сломаться суррогатные пары и неверное толкование «символов». Например:
// DO NOT USE THIS!
> '????'.split('')
[ '�', '�', '�', '�', '�', '�', '�', '�' ]
Я предлагаю использовать одну из следующих функций ES2015 для правильной обработки этих последовательностей символов.
Spread-оператор ( уже ответил от имени пользователя вставки здесь)
> [...'????']
[ '?', '?', '?', '?' ]
> Array.from('????')
[ '?', '?', '?', '?' ]
> '????'.split(/(?=[\s\S])/u)
[ '?', '?', '?', '?' ]
Используйте /(?=[\s\S])/u
вместо /(?=.)/u
, поскольку .
не соответствует символам новой строки .
Если вы все еще находитесь в эпохе ES5.1 (или если ваш браузер неправильно обрабатывает это регулярное выражение - например, Edge), вы можете использовать эту альтернативу (передано Babel ):
> '????'.split(/(?=(?:[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))/);
[ '?', '?', '?', '?' ]
Обратите внимание, что Бабель также пытается правильно обрабатывать непревзойденных суррогатов. Тем не менее, это не работает для непревзойденных низких суррогатов.
Проверьте все в вашем браузере:
function run_test(){
str=document.getElementById('nonBMP').checked ? '?_NL_?_HIGH_?_LOW_?' : '0_NL_1_HIGH_2_LOW_3';
str=str.replace('_NL_' ,document.getElementById('nl' ).checked ? '\n' : '');
str=str.replace('_HIGH_',document.getElementById('high').checked ? '?'.charAt(0) : '');
str=str.replace('_LOW_' ,document.getElementById('low' ).checked ? '?'.charAt(1) : '');
//wrap all examples into try{ eval(...) } catch {} to aloow script execution if some syntax not supported (for example in Internet Explorer)
document.getElementById("testString" ).innerText=JSON.stringify(str);
try { document.getElementById("splitEmpty" ).innerText=JSON.stringify(eval('str.split("")')); } catch(err) { }
try { document.getElementById("splitRegexDot").innerText=JSON.stringify(eval('str.split(/(?=.)/u)')); } catch(err) { }
try { document.getElementById("spread" ).innerText=JSON.stringify(eval('[...str]')); } catch(err) { }
try { document.getElementById("arrayFrom" ).innerText=JSON.stringify(eval('Array.from(str)')); } catch(err) { }
try { document.getElementById("splitRegex" ).innerText=JSON.stringify(eval('str.split(/(?=[\\s\\S])/u)')); } catch(err) { }
try { document.getElementById("splitBabel" ).innerText=JSON.stringify(eval('str.split(/(?=(?:[\\0-\\uD7FF\\uE000-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]))/)')); } catch(err) { }
}
document.getElementById('runTest').onclick=run_test;
th, td {
border: 1px solid black;
padding: 4px;
}
<div><input type="checkbox" id="nonBMP" checked /><label for="nonBMP">Codepoints above U+FFFF</label></div>
<div><input type="checkbox" id="nl" checked /><label for="nl" >Newline</label></div>
<div><input type="checkbox" id="high" /><label for="high" >Unmached high surrogate</label></div>
<div><input type="checkbox" id="low" /><label for="low" >Unmached low surrogate</label></div>
<button type="button" id="runTest">Run Test!</button>
<table>
<tr><td>str=</td> <td><div id="testString"></div></td></tr>
<tr><th colspan="2">Wrong:</th></tr>
<tr><td>str.split("")</td> <td><div id="splitEmpty"></div></td></tr>
<tr><td>str.split(/(?=.)/u)</td> <td><div id="splitRegexDot"></div></td></tr>
<tr><th colspan="2">Better:</th></tr>
<tr><td>[...str]</td> <td><div id="spread"></div></td></tr>
<tr><td>Array.from(str)</td> <td><div id="arrayFrom"></div></td></tr>
<tr><td>str.split(/(?=[\s\S])/u)</td> <td><div id="splitRegex"></div></td></tr>
<tr><td>str.split(/(?=(?:[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))/)</td><td><div id="splitBabel"></div></td></tr>
</table>