Показать сообщение отдельно
  #13 (permalink)  
Старый 12.12.2011, 10:26
sinistral
Посмотреть профиль Найти все сообщения от melky
 
Регистрация: 28.03.2011
Сообщений: 5,418

написал всё в пунктиках :

  • общий вид кода :
    (function ... (...) {...} ).apply(...)
    

    создает анонимную функцию с указанным именем и сразу запускает её на выполнение, меняя this внутри неё и передавая аргументы

  • общий вид return
    return ARR[key] << NUM
    

    т.е. создаст массив (ARR), из него выберет значение по ключу (key) и вернёт его значение, сдвинутое в двоичном представлении на NUM битов влево с добавлением нулей.

рассмотрим return поподробней, в нескольких частях
  • ARR
    return *!*[,,~0.[0|0] ]*/!* [ ... ] << ...;
    

    создаст массив с длиной 3, где первый (key==0) и второй (key==1) равны undefined, а последний равен -1. почему ? краткая схема должна показать ход тождественных преобразований
    ~0.[0|0] =>  ~0.[0] => ~undefined => -1
    

    убедитесь сами. причём разложение побитового "НЕ" (~) на тождественную ему математическую операцию ( ~a == -1*(a+1) ) не даст такого же результата, потому что любые арифметические операции (сложение, деление...) с undefined дают NaN :
    alert( ~undefined == -1*(undefined+1) ); // false
    

    итак. наш массив таков :
    [  undefined, undefined, -1 ]
    

    идём дальше.
  • key
    pewpew.__proto__.length && Infinity, -~String(*!*undefined||??*/!*).length >> __proto__
    

    (подчёркнуто то, что неоднозначно : если в текущей области видимости есть переменная pewpew, то будет что-то отличное от undefined)
    ... ну да ладно. посчитаем, что ничего не определялось до запуска функции.
    его формат :
    Код:
    NUM && undefined, NUM >> 2
    значения аргументов подставлены из apply. там ещё length равен undefined - по аналогии с верхним пунктом.

    ... преобразовывается формат в такой (следуем по запятой - она просто возвратит значение справа)
    Код:
    NUM && NUM >> 2
    т.е. в виде кода это :
    pewpew.__proto__.length && undefined, -~String(undefined).length >> 2
    

    обернём в скобки, чтобы пояснить, что операторы в JS работают слева направо :
    ( (NUM&&undefined), NUM) >> NUM
    

    а теперь разбираем:
    pewpew будет указывать на текущую функцию (arguments.callee). её свойство __proto__ равно пустой функции Empty.
    вот тут я почесал репу. я знаю, почему, но не могу объяснить. это вторая стадия понимания (первая - "не понял").. плохо. буду читать
    ну да ладно.

    т.е.
    pewpew.__proto__.toString() == "function Empty(){}"
    

    у этой функции мы получаем количество аргументов length. само собой, оно равно нулю - 0

    т.е. конструкция превращается в такую
    (pewpew.__proto__.length, -~String(undefined).length) >> 2
    

    >> будет работать с результатом запятой.

    результат запятой- то, что находится с правой её стороны.

    код превращается в такой :
    -~String(undefined).length >> 2
    

    этот код приведёт undefined к строке ("undefined", само собой)
    далее он получит её длину (9), далее (от ~) прибавит к ней 1, умножит на -1 и (от -) поставит противоположный знак.
    получаем
    10 >> 2
    

    это равно
    alert( 10 >> 2 ); // 2
    

    идём дальше.
  • <<NUM
    (0. === .0) + Infinity
    

    то, что в скобках - разная форма записи одного и того же числа. разумеется, результат выполнения равен true :
    Код:
    0. => 0   }
                  |  =>   0 === 0    =>    true
    .0 => 0   }
    далее идёт суммирования булевого true, который при приведении к числу становится 1 с undefined (аргумент)
    это равно NaN :
    Код:
    (true + undefined) === NaN
всё.

таким образом, форма записи этой функции расширяется до :
(убрал запятую и &&.)
(function pewpew(Infinity, length, __proto__){

    return [undefined, undefined, -1][ -~String(undefined).length >> 2  ] << NaN;

}).call(typeof pewpew, undefined, undefined, 2);

...проверим, равны ли возвращаемые значения этого кода и оригинального ?
var original = (function pewpew(Infinity, length, __proto__) {
  return [,,~0.[0|0]][pewpew.__proto__.length && Infinity, -~String(this).length >> __proto__] << (0. === .0) + Infinity;
}).apply(typeof pewpew, [,,2]);

var remixed = (function pewpew(Infinity, length, __proto__){
    return [undefined, undefined, -1][ -~String(undefined).length >> 2  ] << NaN;
}).call(typeof pewpew, undefined, undefined, 2);

alert( original === remixed );

да. всё хорошо


если подставить переменные, то получается (без return. это уже не функция. просто код) :

[undefined, undefined, -1][2] << NaN

это эквивалентно :
-1 << NaN

и равно это
alert( -1 << NaN ); //  -1



THE END

Последний раз редактировалось melky, 12.12.2011 в 20:51.
Ответить с цитированием