Как работает этот волшебный 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 65

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 объекта. Умно? Вы спорим!