Skip to content

Instantly share code, notes, and snippets.

@vvscode
Created September 4, 2016 17:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vvscode/c0498c642a21424fc154bdb1ccd2558b to your computer and use it in GitHub Desktop.
Save vvscode/c0498c642a21424fc154bdb1ccd2558b to your computer and use it in GitHub Desktop.
God Mode in JavaScript
// что возвращает эта функция?
(function fun(Infinity, length, __proto__)
{
return [,,~0.[0|0]][fun.__proto__.length && Infinity, -~String(this).length >> __proto__] << (0. === .0) + Infinity;
}).apply(typeof fun, [,,2]);
// рассмотрим массив с аргументами:
// "0" in [,,2] => false
// "1" in [,,2] => false
// "2" in [,,2] => true
// элементы на индексах 0 и 1 неопределены
// такого состояния можно достичь и так:
// var array = new Array(3);
// array[2] = 2;
// функционально этот массив похож на [ undefined, undefined, 2 ]
// однако "0" in [ undefined, undefined, 2 ] => true
(function fun(Infinity, length, __proto__)
{
return [ undefined, undefined, ~0.[0|0] ][ fun.__proto__.length && Infinity, -~String(this).length >> __proto__ ] << (0. === .0) + Infinity;
}).apply(typeof fun, [ undefined, undefined, 2 ]);
// typeof всегда возвращает строку-описание типа данных
// то есть typeof typeof %от_чего_угодно% === "string"
// fun доступно лишь внутри именованого функционального выражения
// поэтому typeof fun == "undefined" (unresolvable reference)
// однако из-за временной мертвой зоны блочных объявлений
// оператор typeof может вызвать ошибку в ES6
(function fun(Infinity, length, __proto__)
{
return [ undefined, undefined, ~0.[0|0] ][ fun.__proto__.length && Infinity, -~String(this).length >> __proto__ ] << (0. === .0) + Infinity;
}).apply("undefined", [ undefined, undefined, 2 ]);
// внутри функции fun опеределены локальные перемененные:
// Infinity со значением undefined - перекрывает (overlap) глобальную константу
// length co значением undefined
// __proto__ со значением undefined
// значение this - объект (!) String от "undefined"
// строка не оборачивается в объект в strict mode
// .0 === 0 === 0.
// 1 == true
// 1 + Infinity == Infinity
(function fun(Infinity, length, __proto__)
{
return [ undefined, undefined, ~0.[0|0] ][ fun.__proto__.length && Infinity, -~String(this).length >> __proto__ ] << Infinity;
}).apply("undefined", [ undefined, undefined, 2 ]);
// далее определяется массив (первые квадратные скобки)
// затем к новосозданному массиву обращаются по индексу (вторые квадратные скобки)
// 0.[0|0] === 0.[0] === 0[0] === undefined (обращение к свойству)
// ~undefined === ~NaN === ~0 === -1 (побайтовое отрицание)
// битвайсные операции преобразовывают числа в Int32
// ~Infinity === ~-Infinity === ~0 === -1
(function fun(Infinity, length, __proto__)
{
return [ undefined, undefined, -1 ][ fun.__proto__.length && Infinity, -~String(this).length >> __proto__ ] << Infinity;
}).apply("undefined", [ undefined, undefined, 2 ]);
// свойство prototype определено лишь на функциях:
// fun.prototype !== fun.__proto__
// fun.prototype.constructor === fun (зачастую)
// прототипом же fun является Function.prototype
// что в свою очередь есть функция без формальных аргументов
// следственно ее свойство length возвращает 0
// 0 && Infinity === 0
(function fun(Infinity, length, __proto__)
{
return [ undefined, undefined, -1 ][ 0, -~String(this).length >> 2 ] << Infinity;
}).apply("undefined", [ undefined, undefined, 2 ]);
// String(this) === "undefined" (объект String становится примитивом)
// String(this).length === 9
// операторы - и ~ в одной группе прецедентности
// поэтому -~9 === -(~9), что равно десяти
// 10 >> 2 === 2 (битвайсный сдвиг)
(function fun(Infinity, length, __proto__)
{
return [ undefined, undefined, -1 ][ 0, 2 ] << Infinity;
}).apply("undefined", [ undefined, undefined, 2 ]);
// рассмотрим бинарный оператор ,
// он эвалюирует оба операнда и возвращает результат оценивания второго
// имеем [ undefined, undefined, -1 ][ 2 ]
(function fun(Infinity, length, __proto__)
{
return -1 << Infinity;
}).apply("undefined", [ undefined, undefined, 2 ]);
// -1 << Infinity === -1 << 0 (как упомянуто выше)
(function fun(Infinity, length, __proto__)
{
return -1;
}).apply("undefined", [ undefined, undefined, 2 ]);
// итого: -1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment