JavaScript (ECMAScript6), 2 байта на строку
'\
'[
'\
b\
i\
g'
][
'\
c\
o\
n\
s\
t\
r\
u\
c\
t\
o\
r'
][
'\
c\
a\
l\
l'
](
0,
`\
n\
=\
p\
r\
o\
m\
p\
t\
(\
'\
'\
)\
;\
i\
=\
0\
;\
f\
o\
r\
(\
;\
+\
+\
i\
<\
=\
n\
;\
c\
o\
n\
s\
o\
l\
e\
.\
l\
o\
g\
(\
i\
%\
5\
?\
f\
|\
|\
i\
:\
f\
+\
'\
P\
i\
e\
'\
)\
)\
f\
=\
i\
%\
3\
?\
'\
'\
:\
'\
A\
p\
p\
l\
e\
'\
`)
()
Длинное объяснение
То, как мы можем сделать строки короче, - это преобразование кода в строку и экранирование концов строки, это накладывает ограничение в 2 байта на строку.
Так alert(1)
становится
"\
a\
l\
e\
r\
(\
1\
)"
Но теперь ваш код является строкой, поэтому нам нужно выполнить строку как код. Я знаю как минимум 4 способа, которыми вы можете выполнить строку как код:
- Eval (код) . Что занимает не менее 5 байтов для вызова
eval(
- setTimeout (код, время ожидания) . Запускает функцию асинхронно, но при желании, если вы передадите строку, она вызовет eval внутри.
- Вы можете воспользоваться DOM и поместить свой код в
onclick=""
атрибут, но мне не удалось сделать короткую часть создания элемента короткой.
- Вызывая конструктора Function new Function () проанализирует ваш код в анонимной функции, которую вы можете вызвать позже (я использовал это).
Все родные функция живет внутри окна объекта и в JavaScript вы можете получить доступ свойств объектов с помощью точечной нотации так eval()
будет window.eval()
, или вы можете получить доступ к свойствам с помощью квадратных скобок window['eval']()
. Вы можете воспользоваться этим, чтобы разбить eval
несколько строк, используя метод, описанный ранее. Но вы все равно должны ввести окно , одна хитрость в том, что если вы не находитесь внутри рамки, верх переменная также является окном, поэтому window.eval становится top.eval (на 3 байта меньше).
w=top
w['eval']
You can shorten the assignment using parenthesis
w=(
top
)
w[
'e\
av\
al'
](
/*string*/
)
Так что это сделает код минимум 3 байта. Чтобы сделать код 2 байта, я использовалnew Function(/*string*/);
конструктор, но мне пришлось проявить творческий подход, чтобы получить к нему доступ без необходимости набирать его.
Во-первых, конструктор Function позволяет вам вызывать его как функцию, опуская ключевое слово new, это сокращает 4 байта, но это также важно по другой причине. Вызов конструктора как функции по-прежнему возвращает экземпляр, что позволяет намnew Function(code)
к Function(code)
. Еще одна важная вещь - это то, что конструктор Function имеет call
метод, который позволяет вам вызывать любую функцию, но переопределяет эту ссылку, а сам конструктор Function является функцией, которую вы можете вызывать для нее сам метод, напримерFunction.call(null, code)
.
Все нативные функции являются экземплярами конструктора Function, а все объекты в javascript имеют свойство constructor . Таким образом, вы можете иметь доступ к конструктору функций для любой встроенной функции, например alert.constructor
, используя вызов метод мы можем выполнить конструктор как функцию. Теперь у нас есть alert.constructor.call (null, code), возвращающий функцию.
объединяя предыдущие течиники, мы можем превратить их в alert['constructor']['call'](null, code)
Теперь нам просто нужно найти функцию или метод с коротким именем, поэтому я выбираю метод big () внутри конструктора String. Так что я могу получить к нему доступ напрямую из пустой строки"".big
"".big.constructor.call(null, "code")();
''['big']['constructor']['call'](0,'/* code */')()
Тогда я просто разбил каждую вещь в 2 байта
Короткий эр объяснение (TLDR)
Я получаю доступ к новому конструктору Function (code) для анализа строки вместо eval (code) . Этот конструктор доступен для любой встроенной функции, выполняя функцию anyFunction. конструктор , вроде alert.constructor===Function
. Я использую функцию / метод внутри String.prototype.big, String.prototype.big.constructor.call(null, /*string*/)
но обращаюсь к нему напрямую из строкового литерала "".big
и превращаю его в скобочную запись . ""['big']['constructor']['call'](0, CODE)
чтобы иметь возможность сломать его с помощью \
.