Магія JavaScript: що можна зробити, використовуючи лише 6 символів?


Дізнайтесь більше про нові кар'єрні можливості в EchoUA. Цікаві проекти, ринкова оплата, гарний колектив. Надсилайте резюме та приєднуйтеся до нас.

JavaScript – це одночасно дивна і чудова мова, яка дозволяє нам писати абсолютно маячний код, що є валідним. Він намагається допомагати нам, конвертуючи величини в потрібні типи залежно від того, як ми з ними працюємо.

Якщо ми додаємо рядок до чогось, результат буде конвертований в рядок.

Якщо ми припишемо ліворуч від чогось плюс або мінус, буде зроблена спроба конвертації рядка в число.

Якщо на щось навісити логічне заперечення, результат буде представлений як логічна величина.

Ми можемо використати це і творити магію, використовуючи лише ці символи: [, ], (, ), ! і +. Якщо Ви читаєте статтю не з мобільного пристрою, то можете відкрити консоль у браузері й виконувати весь код там.

Розпочнемо із засад. Те, що варто запам’ятати:

  1. Префікс ! конвертує в Boolean.
  2. Префікс + конвертує в число.
  3. Складання з [] конвертує в рядок.

Ось приклад:

![] === false+[] === 0[]+[] === ""

Крім того, треба знати, що символи з рядка можна отримувати в такий спосіб:

"hello"[0] === "h"

Також запам’ятайте, що числа можна отримувати складанням інших чисел у рядковому виді та конвертацією результату в числовий формат:

+("1" + " 1") === 11

Спробуємо використати розглянуті властивості й отримати букву a.

![] === false![]+[] === "false"+!![] === 1------------------------ (![]+[])[+!![]] === "a" // same as " false"[1]

Потішно!

Таким чином, шляхом нехитрих махінацій ми можемо отримати всі букви зі слів true і false. a, e, f, l, r, s, t, u. Добре, а чи можемо ми взяти букви ще десь?

Ну, ще є undefined, який і можна отримати, зробивши щось безглузде, на кшталт [][[]]. Конвертація в рядок дасть нам букви d, i і n.

[][[]] + [] === "undefined"

Використовуючи ці букви, можна скласти слова fill, filter і find. Звичайно, є й інші доступні слова, але цінність цих слів полягає в тому, що вони – методи масивів. Це означає, що вони є частиною об’єкта Array і їх можна викликати прямо для масивів-сутностей. Наприклад, [2,1].sort ().

Крім того, треба пам’ятати, що властивості об’єкта в JS можна використати як через точку, так і через квадратні дужки. Оскільки методи масиву – це властивості об’єкта Array, ми можемо викликати їх, використовуючи дужки замість точки.

Інакше кажучи, [2,1]["sort"]() – це те саме, що й [2,1].sort ().

Давайте подивимося, що станеться, коли ми спробуємо використати один з доступних нам методів, не викликаючи його.

[]["fill"]

Це видасть function fill (){ [native code] }. Конвертуємо заголовок методу в рядок:

[]["fill"]+[] === "function fill (){ [native code] }"

І отримаємо нові символи: c, o, v, (, ), {, [, ], }, .

З літер c та o, можемо скласти слово constructor. constructor – це метод, який є в усіх JS-об’єктів, і він повертає їх функцію-конструктор.

Отримаємо рядкове представлення всіх конструкторів наших об’єктів:

true["constructor"] + [] === "function Boolean (){ [native code] }" 0["constructor"] + [] === "function Number (){ [native code] }" ""["constructor"] + [] === "function String (){ [native code] }"
[]["constructor"] + [] === "function Array (){ [native code] }"

З цих рядків ми можемо поповнити наш арсенал наступними символами: B, N, S, A, m, g, y.

Тепер ми складемо "toString", функцію, яку можна використати з квадратними дужками. Тільки цього разу ми викличемо її.

(10)["toString"]() === "10"

Тепер ми вже можемо конвертувати в рядок все, що завгодно, оскільки нам це допоможе?

Якщо я скажу Вам, що метод toString типу Number володіє секретним аргументом radix, який міняє основу поверненого числа перед конвертацією в рядок. Дивіться:

(12)["toString"](10) === "12" // base 10 - normal to us (12)["toString"](2) === "1100" // base 2, or binary, for 12 (12)["toString"](8) === "14" // base 8 (octonary) for 12 (12)["toString"](16) === "c" // hex for 12

Навіщо зупинятися на 16? Максимум – це 36, чого вистачає на всі символи 0 -9 і a -z. Тепер ми можемо отримати будь-яку цифру або літеру:

(10)["toString"](36) === "a" (35)["toString"](36) === "z"

Відмінно! Постає запитання: “Як же пунктуаційні символи і заголовні літери?”. Йдемо далі!

Залежно від того, де Ви виконуєте свій JS-код, він може отримувати, а може і не отримувати доступ до заздалегідь визначених об’єктів і даних. Є вірогідність, що при запуску в браузері Ви зможете отримати доступ до обгорткових методів HTML.

Наприклад, bold – це метод String, що обертає рядок на тег <b>.

"test"["bold"]() === "test"

Це дасть нам символи <, > і /.

Можливо, Ви чули про функцію escape. По суті, вона конвертує рядок в URI-формат, який можуть розпізнати браузери. Якщо ми передамо їй пропуск, то отримаємо %20. Передамо < – отримаємо %3С. Ця заголовна C дуже важлива для отримання інших символів.

Завдяки їй ми можемо використати функцію fromCharCode, що повертає символ Юні-коду за цим десятковим представленням. Вона є частиною об’єкта String, який можна отримати, викликавши конструктор будь-якого рядка.w

""["constructor"]["fromCharCode"](65) === "A"""["constructor"]["fromCharCode"](46) === "".

Для отримання десяткових представлень символів можна використати сайт Unicode lookup.

Добре, тепер ми можемо написати що завгодно у вигляді рядка і виконати будь-яку функцію, яка належить типам Array, String, Number, Boolean або Object, через їх конструктори. Немало для 6 символів. Це ще не кінець.

Запитання: Чим є конструктор будь-якої функції?

Відповідь: function Function (){ [native code] }, справжній об’єкт Function.

[]["fill"]["constructor"] === Function

Використовуючи його, ми можемо передати рядок коду, щоб створити реальну функцію.

Function ("alert ('test')");

Отримаємо:

Function anonymous (){ alert ('test')}

Що можна викликати відразу ж, просто додавши наприкінці (). Так, тепер ми можемо виконувати рядки коду!

Ось тепер все!

Ми можемо отримати доступ до будь-якого символу, об’єднувати їх у валідний код і виконувати його. Це означає, що JS є повною, за Тьюрінгом, мовою із 6 символів [, ], (, ), + і !.

Не вірите? Запустіть це в консолі:

Якщо Ви читаєте статтю з мобільного пристрою, код вищий – це виконувана функція alert ("wtf").

Ось інструмент, який може автоматизувати конверсію, а ось так він переводить кожен символ.

Ну і як це може згодитися?

Ніяк eBay нещодавно “нахімічив” щось у коді, й продавці змогли вбудовувати виконуваний JS у свої сторінки, використовуючи тільки ці символи, але такі атаки дуже рідкісні. Можна подумати про обфускацію, але, будемо чесними, є кращі методи.

Дякую за увагу!

Переклад статті “A Javascript journey with only six characters”

Київ, Харків, Одеса, Дніпро, Запоріжжя, Кривий Ріг, Вінниця, Херсон, Черкаси, Житомир, Хмельницький, Чернівці, Рівне, Івано-Франківськ, Кременчук, Тернопіль, Луцьк, Ужгород, Кам'янець-Подільський, Стрий - за статистикою саме з цих міст програмісти найбільше переїжджають працювати до Львова. А Ви розглядаєте relocate?


Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *