由于接口签名需要,JavaScript encodeURIComponent方法本身标准跟PHP不一致,网上找了很久,居然没有一个完整可用的,决定参考大神的半成品自己写一个。
可用标准:
1. 特殊符号encode结果一致;
2. emoji表情支持;
function urlEncode(str) {
let strArr = [];
let output = '';
strArr = Array.from(str);
for (let v of strArr) {
let regRule = /\uD83C[\uDF00-\uDFFF]|\uD83D[\uDC00-\uDE4F]/g;
output += v.match(regRule) ? encodeURIComponent(v) : encodeNoEmoji(v);
}
return output;
}
function encodeNoEmoji(str) {
var output = '';
var x = 0;
str = utf16to8(str.toString());
var regex = /(^[a-zA-Z0-9-_.]*)/;
while (x < str.length) {
var match = regex.exec(str.substr(x));
if (match !== null && match.length > 1 && match[1] !== '') {
output += match[1];
x += match[1].length;
} else {
if (str[x] === ' ')
output += '+';
else {
var charCode = str.charCodeAt(x);
var hexVal = charCode.toString(16);
output += '%' + ( hexVal.length < 2 ? '0' : '' ) + hexVal.toUpperCase();
}
x++;
}
}
return output;
}
function utf16to8(str) {
var out, i, len, c;
out = "";
len = str.length;
for(i = 0; i < len; i++) {
c = str.charCodeAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
out += str.charAt(i);
} else if (c > 0x07FF) {
out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
} else {
out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
}
}
return out;
}
测试字符串(注意引号转义):我测试字符串是?魑1?魅 魍?魉 11\1!".@#$%&'()*+-_,/:;<=>?[]^`{|}~%
JS测试结果:%E6%88%91%E6%B5%8B%E8%AF%95%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%98%AF%F0%9F%98%80%E9%AD%911%F0%9F%8F%B4%E9%AD%85++%E9%AD%8D%F0%9F%90%99%E9%AD%89+11%5C1%21%22.%40%23%24%25%26%27%28%29%2A%2B-_%2C%2F%3A%3B%3C%3D%3E%3F%5B%5D%5E%60%7B%7C%7D%7E%25
PHP测试结果:%E6%88%91%E6%B5%8B%E8%AF%95%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%98%AF%F0%9F%98%80%E9%AD%911%F0%9F%8F%B4%E9%AD%85++%E9%AD%8D%F0%9F%90%99%E9%AD%89+11%5C1%21%22.%40%23%24%25%26%27%28%29%2A%2B-_%2C%2F%3A%3B%3C%3D%3E%3F%5B%5D%5E%60%7B%7C%7D%7E%25
注意:本方法只适用于UTF-8编码。