Как работает этот волшебный Javascript?
Это небольшой javascript, который предупреждает "Hello world":
゚ω゚ノ=/`m´)ノ~┻━┻//*´∇`*/['_'];o=(゚ー゚)=_=3;c=(゚Θ゚)=(゚ー゚)-(゚ー゚);(゚Д゚)=(゚Θ゚)=(o^_^o)/(o^_^o);(゚Д゚)={゚Θ゚:'_',゚ω゚ノ:((゚ω゚ノ==3)+'_')[゚Θ゚],゚ー゚ノ:(゚ω゚ノ+'_')[o^_^o-(゚Θ゚)],゚Д゚ノ:((゚ー゚==3)+'_')[゚ー゚]};(゚Д゚)[゚Θ゚]=((゚ω゚ノ==3)+'_')[c^_^o];(゚Д゚)['c']=((゚Д゚)+'_')[(゚ー゚)+(゚ー゚)-(゚Θ゚)];(゚Д゚)['o']=((゚Д゚)+'_')[゚Θ゚];(゚o゚)=(゚Д゚)['c']+(゚Д゚)['o']+(゚ω゚ノ+'_')[゚Θ゚]+((゚ω゚ノ==3)+'_')[゚ー゚]+((゚Д゚)+'_')[(゚ー゚)+(゚ー゚)]+((゚ー゚==3)+'_')[゚Θ゚]+((゚ー゚==3)+'_')[(゚ー゚)-(゚Θ゚)]+(゚Д゚)['c']+((゚Д゚)+'_')[(゚ー゚)+(゚ー゚)]+(゚Д゚)['o']+((゚ー゚==3)+'_')[゚Θ゚];(゚Д゚)['_']=(o^_^o)[゚o゚][゚o゚];(゚ε゚)=((゚ー゚==3)+'_')[゚Θ゚]+(゚Д゚).゚Д゚ノ+((゚Д゚)+'_')[(゚ー゚)+(゚ー゚)]+((゚ー゚==3)+'_')[o^_^o-゚Θ゚]+((゚ー゚==3)+'_')[゚Θ゚]+(゚ω゚ノ+'_')[゚Θ゚];(゚ー゚)+=(゚Θ゚);(゚Д゚)[゚ε゚]='';(゚Д゚).゚Θ゚ノ=(゚Д゚+゚ー゚)[o^_^o-(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ+'_')[c^_^o];(゚Д゚)[゚o゚]='"';(゚Д゚)['_']((゚Д゚)['_'](゚ε゚+(゚Д゚)[゚o゚]+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+(゚Θ゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+((゚ー゚)+(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)+(o^_^o))+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)+(o^_^o))+(゚ー゚)+(゚Д゚)[゚ε゚]+((゚ー゚)+(゚Θ゚))+(c^_^o)+(゚Д゚)[゚ε゚]+(゚ー゚)+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚Θ゚)+(c^_^o)+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+((゚ー゚)+(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+((゚ー゚)+(o^_^o))+(゚Д゚)[゚ε゚]+(゚ー゚)+(c^_^o)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)-(゚Θ゚))+((゚ー゚)+(o^_^o))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+((゚ー゚)+(o^_^o))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)+(o^_^o))+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚ー゚)+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+((゚ー゚)+(゚Θ゚))+(゚Θ゚)+(゚Д゚)[゚o゚])(゚Θ゚))('_');
хороший вариант:
゚ω゚ノ = /`m´)ノ~┻━┻//*´∇`*/['_'];
o = (゚ー゚) = _ = 3;
c = (゚Θ゚) = (゚ー゚) - (゚ー゚);
(゚Д゚) = (゚Θ゚) = (o^_^o)/(o^_^o);
(゚Д゚) = {
゚Θ゚: '_',
゚ω゚ノ: ((゚ω゚ノ==3)+'_')[゚Θ゚],
゚ー゚ノ: (゚ω゚ノ+'_')[o^_^o-(゚Θ゚)],
゚Д゚ノ: ((゚ー゚==3)+'_')[゚ー゚]
};
(゚Д゚)[゚Θ゚] = ((゚ω゚ノ==3)+'_')[c^_^o];
(゚Д゚)['c'] = ((゚Д゚)+'_')[(゚ー゚)+(゚ー゚)-(゚Θ゚)];
(゚Д゚)['o'] = ((゚Д゚)+'_')[゚Θ゚];
(゚o゚)=(゚Д゚)['c'] + (゚Д゚)['o'] + (゚ω゚ノ + '_')[゚Θ゚] + ((゚ω゚ノ==3) + '_')[゚ー゚] + ((゚Д゚) + '_')[(゚ー゚) + (゚ー゚)] + ((゚ー゚==3) + '_')[゚Θ゚] + ((゚ー゚==3) + '_')[(゚ー゚) - (゚Θ゚)] + (゚Д゚)['c'] + ((゚Д゚) + '_')[(゚ー゚) + (゚ー゚)] + (゚Д゚)['o'] + ((゚ー゚==3) + '_')[゚Θ゚];
(゚Д゚)['_'] = (o^_^o)[゚o゚][゚o゚];
(゚ε゚) = ((゚ー゚==3) + '_')[゚Θ゚] + (゚Д゚).゚Д゚ノ + ((゚Д゚) + '_')[(゚ー゚) + (゚ー゚)] + ((゚ー゚==3) + '_')[o^_^o-゚Θ゚] + ((゚ー゚==3) + '_')[゚Θ゚] + (゚ω゚ノ+'_')[゚Θ゚];
(゚ー゚) += (゚Θ゚);
(゚Д゚)[゚ε゚] = '';
(゚Д゚).゚Θ゚ノ = (゚Д゚+゚ー゚)[o^_^o-(゚Θ゚)];
(o゚ー゚o) = (゚ω゚ノ+'_')[c^_^o];
(゚Д゚)[゚o゚] = '"';
(゚Д゚)['_']((゚Д゚)['_'](゚ε゚+(゚Д゚)[゚o゚]+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+(゚Θ゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+((゚ー゚)+(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)+(o^_^o))+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)+(o^_^o))+(゚ー゚)+(゚Д゚)[゚ε゚]+((゚ー゚)+(゚Θ゚))+(c^_^o)+(゚Д゚)[゚ε゚]+(゚ー゚)+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚Θ゚)+(c^_^o)+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+((゚ー゚)+(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+((゚ー゚)+(o^_^o))+(゚Д゚)[゚ε゚]+(゚ー゚)+(c^_^o)+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)-(゚Θ゚))+((゚ー゚)+(o^_^o))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+((゚ー゚)+(o^_^o))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((o^_^o)+(o^_^o))+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+(゚Θ゚)+((゚ー゚)+(゚Θ゚))+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚Θ゚)+(゚ー゚)+(゚ー゚)+(゚Д゚)[゚ε゚]+(゚ー゚)+((o^_^o)-(゚Θ゚))+(゚Д゚)[゚ε゚]+((゚ー゚)+(゚Θ゚))+(゚Θ゚)+(゚Д゚)[゚o゚])(゚Θ゚))('_');
JSFiddle
Взято отсюда:https://codegolf.stackexchange.com/a/24041/17049
кто-нибудь знает, как это работает? Я даже не вижу alert в этом коде.
3 ответа:
прежде чем смотреть ближе на код, вы должны знать, что с JavaScript 1.5 коды разрешается содержать не только символы ASCII, но и символы Юникода.
в этом случае многие из этих забавных последовательностей являются просто идентификаторами. После обмена этими идентификаторами на более простые идентификаторы и удаления ненужных комментариев и скобок код выглядит следующим образом:
a = /`m´)ノ~┻━┻/['_']; o = b = _ = 3; c = d = b-b; e = d = o^_^o/o^_^o; e = { d: '_', a: ((a==3)+'_')[d], h: (a+'_')[o^_^o-d], i: ((b==3)+'_')[b] }; e[d] = ((a==3)+'_')[c^_^o]; e['c'] = (e+'_')[b+b-d]; e['o'] = (e+'_')[d]; f = e['c']+e['o']+(a+'_')[d]+((a==3)+'_')[b]+(e+'_')[b+b]+((b==3)+'_')[d]+((b==3)+'_')[b-d]+e['c']+(e+'_')[b+b]+e['o']+((b==3)+'_')[d]; e['_'] = (o^_^o)[f][f]; g = ((b==3)+'_')[d]+e.i+(e+'_')[b+b]+((b==3)+'_')[o^_^o-d]+((b==3)+'_')[d]+(a+'_')[d]; b += d; e[g] = '\'; e.j = (e+b)[o^_^o-d]; obo = (a+'_')[c^_^o]; e[f] = '\"'; e['_'](e['_'](g+e[f]+e[g]+d+b+d+e[g]+d+(b+d)+b+e[g]+d+b+(b+d)+e[g]+d+((o^_^o)+(o^_^o))+((o^_^o)-d)+e[g]+d+((o^_^o)+(o^_^o))+b+e[g]+(b+d)+(c^_^o)+e[g]+b+((o^_^o)-d)+e[g]+d+d+(c^_^o)+e[g]+d+b+(b+d)+e[g]+d+(b+d)+b+e[g]+d+(b+d)+b+e[g]+d+(b+d)+(b+(o^_^o))+e[g]+b+(c^_^o)+e[g]+d+((o^_^o)-d)+(b+(o^_^o))+e[g]+d+(b+d)+(b+(o^_^o))+e[g]+d+((o^_^o)+(o^_^o))+((o^_^o)-d)+e[g]+d+(b+d)+b+e[g]+d+b+b+e[g]+b+((o^_^o)-d)+e[g]+(b+d)+d+e[f])(d))('_');теперь мы можем оценить каждое утверждение по время:
a = /`m´)ノ~┻━┻/['_']оценивает вa = undefinedo = b = _ = 3назначаетo,bи_целое3c = d = b-bназначаетcиdцелое0e = d = o^_^o/o^_^oназначаетeиdцелое1(o^_^oзначение 3 3 исключающее ИЛИ исключающее или 3, который дает 3)e = { d: '_', a: ((a==3)+'_')[d], h: (a+'_')[o^_^o-d], i: ((b==3)+'_')[b] }назначаетeобъект{ d: '_', a: 'a', h: 'd', i: 'e' }e[d] = ((a==3)+'_')[c^_^o]назначаетe[1]строка'f'e['c'] = (e+'_')[b+b-d]назначаетe['c']строка'c'e['o'] = (e+'_')[d]назначаетe['o']строка'o'это все было просто настройка и установлены следующие переменные:
a = undefined b = 3 c = 0 d = 1 e = { 1: "f", a: "a", c: "c", d: "_", h: "d", i: "e", o: "o" }следующее утверждение является первым, что строит что-то:
f = e['c'] + // => "c" e['o'] + // => "o" (a+'_')[d] + // => "undefined_"[1] = "n" ((a==3)+'_')[b] + // => "false_"[3] = "s" (e+'_')[b+b] + // => "object_"[6] = "t" ((b==3)+'_')[d] + // => "true_"[1] = "r" ((b==3)+'_')[b-d] + // => "true_"[2] = "s" e['c'] + // => "c" (e+'_')[b+b] + // => "object_"[6] = "t" e['o'] + // => "o" ((b==3)+'_')[d]; // => "true"[1] = "r"так
f = "constructor". В следующем заявлении"constructor"используется для извлечения функции:e['_'] = (o^_^o)[f][f]этот эквивалентно
(3).constructor.constructor, который дает функцииFunction, так:e['_'] = Functionэтой
Functionфункция особенная, так как можно динамически создавать функции, передавая ей код тела функции через параметр:f = Function("alert(1)") // equivalent to f = function() { alert(1) }я пропущу следующие несколько операторов и просто напишу результирующие переменные и значения:
a = undefined b = 4 c = 0 d = 1 e = { 1: "f", _: Function, a: "a", c: "c", constructor: "\"", d: "_", h: "d", i: "e", j: "b", o: "o", return: "\" } f = "constructor" obo = "u"последнее утверждение делает заключительную работу:
e['_'](e['_'](g+e[f]+e[g]+d+b+d+e[g]+d+(b+d)+b+e[g]+d+b+(b+d)+e[g]+d+((o^_^o)+(o^_^o))+((o^_^o)-d)+e[g]+d+((o^_^o)+(o^_^o))+b+e[g]+(b+d)+(c^_^o)+e[g]+b+((o^_^o)-d)+e[g]+d+d+(c^_^o)+e[g]+d+b+(b+d)+e[g]+d+(b+d)+b+e[g]+d+(b+d)+b+e[g]+d+(b+d)+(b+(o^_^o))+e[g]+b+(c^_^o)+e[g]+d+((o^_^o)-d)+(b+(o^_^o))+e[g]+d+(b+d)+(b+(o^_^o))+e[g]+d+((o^_^o)+(o^_^o))+((o^_^o)-d)+e[g]+d+(b+d)+b+e[g]+d+b+b+e[g]+b+((o^_^o)-d)+e[g]+(b+d)+d+e[f])(d))('_');это эквивалентно к:
Function(Function( … )(1))('_')длинное выражение строит следующую строку:
return"145240544777244"экранированная строка вычисляет:
alert("Hello World")этой
returnкод передаетсяFunction, который создает анонимную функцию, такую как:function anonymous() { return"145240544777244"; }, который, как мы знаем, эквивалентно:
function anonymous() { return"alert(\"Hello World\")"; }затем эта функция выполняется с помощью
1как параметр, который возвращает результирующую строку:alert("Hello World")это затем передается к
Functionопять же, что создает новую анонимную функцию:function anonymous() { alert("Hello World"); }наконец, эта функция также вызывается с
'_'в качестве параметра.
здесь много чего есть. Круглые скобки вокруг переменных не являются функциональными.
в основном он строит эту строку:
return"145240544777244"который является экранированной версией
return "alert(\"Hello World\")"и, наконец, это:
Function(Function('return "alert(\"Hello World\")"')())()двойной
Functionкажется произвольным, но это не так.Function()интерпретирует обратные косые черты в строке как escape-символы. Так что первый вызов декодирует, а второй выполняет.Function("return '\110\145\154\154\157'")() // => "Hello"это тот же самый код, лучше отформатированный и с "нормальными" именами переменных;
var1=/`m´)ノ~┻━┻//*´∇`*/['_']; three=(threeThenFour)=_=3; c=(one)=(threeThenFour)-(threeThenFour); (anObject)=(one)=(three)/(three); (anObject)={ one:'_', var1:((var1==3)+'_')[one], var2ノ:(var1+'_')[three-(one)], var4ノ:((threeThenFour==3)+'_')[threeThenFour] }; (anObject)[one]=((var1==3)+'_')[c ^ _ ^ three]; (anObject)['c']=((anObject)+'_')[(threeThenFour)+(threeThenFour)-(one)]; (anObject)['three']=((anObject)+'_')[one]; (theConstructor)=(anObject)['c']+ (anObject)['three']+ (var1+'_')[one]+ ((var1==3)+'_')[threeThenFour]+ ((anObject)+'_')[(threeThenFour)+(threeThenFour)]+ ((threeThenFour==3)+'_')[one]+ ((threeThenFour==3)+'_')[(threeThenFour)-(one)]+ (anObject)['c']+ ((anObject)+'_')[(threeThenFour)+(threeThenFour)]+ (anObject)['three']+ ((threeThenFour==3)+'_')[one]; // theConstructor => "constructor" (anObject)['_']=(three)[theConstructor][theConstructor]; (theReturn)=((threeThenFour==3)+'_')[one]+ (anObject).var4ノ+ ((anObject)+'_')[(threeThenFour)+(threeThenFour)]+ ((threeThenFour==3)+'_')[three-one]+ ((threeThenFour==3)+'_')[one]+ (var1+'_')[one]; // theReturn => "return" (threeThenFour)+=(one); (anObject)[theReturn]='\'; (anObject).var3ノ=(anObject+threeThenFour)[three-(one)]; (ovar2o)=(var1+'_')[c ^ _ ^ three]; (anObject)[theConstructor]='\"'; // (anObject)['_'] => Function (anObject)['_']( (anObject)['_'](theReturn+ (anObject)[theConstructor]+ (anObject)[theReturn]+ (one)+ (threeThenFour)+ (one)+ (anObject)[theReturn]+ (one)+ ((threeThenFour)+(one))+ (threeThenFour)+ (anObject)[theReturn]+ (one)+( threeThenFour)+ ((threeThenFour)+(one))+ (anObject)[theReturn]+ (one)+ ((three)+(three))+ ((three)-(one))+ (anObject)[theReturn]+ (one)+ ((three)+(three))+ (threeThenFour)+ (anObject)[theReturn]+ ((threeThenFour)+(one))+ (c ^ _ ^ three)+ (anObject)[theReturn]+ (threeThenFour)+((three)-(one))+ (anObject)[theReturn]+ (one)+(one)+ (c ^ _ ^ three)+ (anObject)[theReturn]+ (one)+ (threeThenFour)+ ((threeThenFour)+(one))+ (anObject)[theReturn]+ (one)+ ((threeThenFour)+(one))+ (threeThenFour)+ (anObject)[theReturn]+ (one)+ ((threeThenFour)+(one))+ (threeThenFour)+ (anObject)[theReturn]+ (one)+ ((threeThenFour)+(one))+ ((threeThenFour)+(three))+ (anObject)[theReturn]+ (threeThenFour)+ (c ^ _ ^ three)+ (anObject)[theReturn]+ (one)+ ((three)-(one))+ ((threeThenFour)+(three))+ (anObject)[theReturn]+ (one)+ ((threeThenFour)+(one))+ ((threeThenFour)+(three))+ (anObject)[theReturn]+ (one)+ ((three)+(three))+ ((three)-(one))+ (anObject)[theReturn]+ (one)+ ((threeThenFour)+(one))+ (threeThenFour)+ (anObject)[theReturn]+ (one)+ (threeThenFour)+ (threeThenFour)+ (anObject)[theReturn]+ (threeThenFour)+ ((three)-(one))+ (anObject)[theReturn]+ ((threeThenFour)+(one))+ (one)+ (anObject)[theConstructor] ) (one) )('_');
позвольте мне объяснить ключевые шаги:
код создает объект с именем Д, а затем добавляет свойство
'_'это имеет значение magic JavaScript конструктор функция. В JavaScript вы можете выполнить любую строку в виде кода, передав ее в конструктор функций.как
(゚Д゚)['_']содержать конструктор функций? Это умная техника, сделанная следующей строкой:(゚Д゚)['_'] = (o^_^o)[゚o゚][゚o゚];здесь o и _ имеет значение 3. Так что
o^_^oвозвращается к 3. Очевидно автор мог бы просто использовать o, потому чтоo^_^oвозвращает то же значение, но я думаю, что у него есть хороший вкус для запутывания :). Таким образом, приведенное выше выражение теперь становится(3)[゚o゚][゚o゚].значение
゚o゚в квадратной скобке устанавливается строка "конструктор", которая была построена путем конкатенации в предыдущем операторе. Он использует очень умный способ построить строку "конструктор", вырывая отдельные символы из встроенных строк JavaScript, таких как "объект", "истина", "ложь" и " неопределенный" которые генерируются из выражений JavaScript, преобразованных в строку. По-видимому, автор не мог найти символ "c", чтобы вырвать из этих встроенных строк, поэтому ему пришлось написать это явно. Обратите внимание, что символ в квадратной скобке-это ゚o゚, который является символом Unicode, а не простой o, используемый в круглых скобках, хотя оба они очень похожи. Когда вы делаете(3)("constructor")возвращает функции конструктора. Конструктор конструктора чисел-это конструктор функций. Так что, делая(3)("constructor")("constructor")вы получаете конструктор функций, который теперь вы можете, наконец, передать произвольную строку для ее выполнения.последняя строка строит строку
"alert(\"Hello World\")"и передает его конструктору функции для выполнения.вопрос в том, как мы получаем эту строку
"alert(\"Hello World\")"без ввода реальных алфавит? Умная техника заключается в использовании\xxxгде xxx-восьмеричное число и переводится в символ. Чтобы получить эту строку цифры вам нужны 0, 1, 2, 3, 4, 5, 6, 7 и 8. Но на самом деле вам не нужно все это, вместо этого вы можете произвести их с помощью простой арифметики с тремя числами 0, 1 и 4. Так например, чтобы произвести символ'a'в "alert" вам нужно ASCII decimal 97 или octal 141, т. е.1. Если у вас есть только 0, 1 и 4, хранящиеся в некотором свойстве выше объекта, вы можете объединить их для получения'a'. Таким образом, вы можете создать любую строку, даже если все, что у вас есть 0, 1 и 4 хранятся в некоторых свойствах object объекта. Умно? Вы спорим!