Как работает этот волшебный 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 = undefined
o = b = _ = 3
назначаетo
,b
и_
целое3
c = d = b-b
назначаетc
иd
целое0
e = 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 объекта. Умно? Вы спорим!