Created
September 4, 2016 17:29
-
-
Save vvscode/c0498c642a21424fc154bdb1ccd2558b to your computer and use it in GitHub Desktop.
God Mode in JavaScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// что возвращает эта функция? | |
(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