Кто-то сказал код гольф? =) * * Тысяча одна
Следующее - моя попытка улучшить свой гандикап, не отставая от времени. Поставляется для вашего удобства.
function decode_base64(s) {
var b=l=0, r='',
m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
s.split('').forEach(function (v) {
b=(b<<6)+m.indexOf(v); l+=6;
if (l>=8) r+=String.fromCharCode((b>>>(l-=8))&0xff);
});
return r;
}
То, что я на самом деле преследовал, было асинхронной реализацией, и, к моему удивлению, получается forEach
в отличие от реализации метода $([]).each
в JQuery очень синхронно.
Если вы также имели в виду такие сумасшедшие представления, задержка 0 window.setTimeout
запустит декодирование base64 асинхронно и выполнит функцию обратного вызова с результатом, когда это будет сделано.
function decode_base64_async(s, cb) {
setTimeout(function () { cb(decode_base64(s)); }, 0);
}
@ Зубная щетка предложила «проиндексировать строку как массив» и избавиться от split
. Эта процедура кажется действительно странной и не уверенной, насколько она будет совместимой, но она поражает другую птичку, так что давайте ее.
function decode_base64(s) {
var b=l=0, r='',
m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
[].forEach.call(s, function (v) {
b=(b<<6)+m.indexOf(v); l+=6;
if (l>=8) r+=String.fromCharCode((b>>>(l-=8))&0xff);
});
return r;
}
Пытаясь найти дополнительную информацию о строке JavaScript в виде массива, я наткнулся на этот профессиональный совет, используя регулярное выражение /./g
для перехода по строке. Это еще больше уменьшает размер кода, заменяя строку на месте и избавляя от необходимости сохранять возвращаемую переменную.
function decode_base64(s) {
var b=l=0,
m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
return s.replace(/./g, function (v) {
b=(b<<6)+m.indexOf(v); l+=6;
return l<8?'':String.fromCharCode((b>>>(l-=8))&0xff);
});
}
Если, однако, вы искали что-то более традиционное, возможно, вам больше понравится.
function decode_base64(s) {
var b=l=0, r='', s=s.split(''), i,
m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
for (i in s) {
b=(b<<6)+m.indexOf(s[i]); l+=6;
if (l>=8) r+=String.fromCharCode((b>>>(l-=8))&0xff);
}
return r;
}
У меня не было завершающей нулевой проблемы, поэтому она была удалена, чтобы оставаться в соответствии с номиналом, но ее легко можно решить с помощью trim()
или trimRight()
, если вы предпочитаете, если это создаст проблему для вас.
т.
return r.trimRight();
Примечание:
В результате получается строка байтов ascii, если вам нужен юникод, проще всего escape
строка байтов, которая затем может быть декодирована с помощью decodeURIComponent
для получения строки юникода.
function decode_base64_usc(s) {
return decodeURIComponent(escape(decode_base64(s)));
}
Поскольку escape
устарело, мы могли бы изменить нашу функцию для поддержки Юникода напрямую, без необходимости escape
или String.fromCharCode
, мы можем создать экранированную строку %
, готовую для декодирования URI.
function decode_base64(s) {
var b=l=0,
m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
return decodeURIComponent(s.replace(/./g, function (v) {
b=(b<<6)+m.indexOf(v); l+=6;
return l<8?'':'%'+(0x100+((b>>>(l-=8))&0xff)).toString(16).slice(-2);
}));
}
NJoy!