Всего с помощью этих 6 символов вы можете написать произвольный код JavaScript!

JavaScript

Вы, наверное, видели всевозможный причудливый код JavaScript, написанный кем-то в Интернете с помощью нескольких разных символов, и это выглядит странно, но это работает! Например это:

(!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]

Угадайте, каков результат? Можете зайти в консоль и попробовать сами.

Выглядит потрясающе, но что, черт возьми, здесь происходит?

На самом деле, вы можете написать почти любую программу на JavaScript, используя эти 6 символов:

[]()!+

Многие люди знают этот трюк, но не многие разработчики знают, как именно он работает. Сегодня давайте посмотрим на принцип выполнения, стоящий за этим. Наша цель — использовать эти несколько символов для записи строки“self”. Поприветствуйте язык Self с помощью этой строки, одного из источников вдохновения для JavaScript.

Фундаментальный

Мы можем опускать другие символы благодаря системе типов JavaScript и механизму преобразования типов данных.

Эти 6 символов выглядят следующим образом:[]можно использовать для создания массивов,!а также+Вы можете выполнить некоторые операции над массивом, а затем использовать()Сгруппируйте эти операции.

Сначала рассмотрим простой массив:

[]

добавить перед массивом!преобразует его в логическое значение. Массивы считаются истиннозначными, поэтому после отрицания становитсяfalse:

![] === false

Значения разных типов нельзя складывать вместе, если только они не преобразованы в аналогичные типы. JavaScript следует предопределенному правилу при выполнении преобразований:

в выражении2 + true, JavaScript будетtrueПреобразуйте в числа, чтобы получить выражение2+1.

в выражении2 + "2", JavaScript преобразует число в строку, чтобы получить2 + "2" === "22".

Эти правила преобразования не так уж плохи, но для других жанров грядут хорошие вещи.

Приведение массива JavaScript

Добавления массива преобразуются в строки и объединяются. Пустой массив преобразуется в пустую строку, поэтому добавление двух массивов приведет к пустой строке.

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

То же самое верно и при добавлении массивов к другим типам значений:

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

Удивлен или нет? мы получили целевую строку"self"Несколько персонажей включены!

Если мы сможем сгенерировать несколько чисел, мы сможем извлечь необходимые символы в правильном порядке:

"false"[3] === "s"

(![] + [])[3] === "s"

Итак, как генерировать числа?

генерировать числа

Как упоминалось ранее, вы можете преобразовывать массивы в логические значения. Тогда, если вы используете знак плюс+Как насчет того, чтобы преобразовать его в числа?

+[] === ???

JavaScript попытается вызвать массивvalueOfметод, но обнаруживается, что этого метода не существует, и тогда вместо него вызываетсяtoString()метод. Таким образом, приведенный выше код эквивалентен:

+[] === +""

Преобразование строки в число дает следующее:

+"42" === 42
+"esg" == NaN
+"" === 0

Пустая строка — этоfalseзначение, например null, undefined и число ноль, поэтому преобразование любого из них в число превратит их в ноль:

+null === 0
+undefined === 0
+false === 0
+NaN === 0
+"" === 0

Следовательно, преобразование массива в число требует его преобразования сначала в строку, а затем в 0:

+[] === +"" === 0

Создан первый номер! Нам еще нужны цифры, вперед:

!0 === !false
!false === true

!0 === true

Буду0Отрицательный, чтобы получить логическое значение, которое истинно. Значение true для преобразования логического значения в число, то есть1:

+true === 1

имеют1, естественно получить2, так называемыйДао рождает одно, одно рождает двоих, двое рождают троих, а трое рождают все вещи....

Используя описанный выше метод преобразования, мы можем легко получить нужные нам числа:

1 === +true == +(!0) ==== +(!(+[])) === +!+[]

1 === +!+[]
2 === +!+[] +!+[]
3 === +!+[] +!+[] +!+[]
4 === +!+[] +!+[] +!+[] +!+[]

Один шаг у двери, все готово

Подводя итог этим правилам:

  • Аранжировки принадлежат истинным ценностям, поймитеfalse:![] // false
  • Массивы преобразуются в символы при добавлении:[] + [] // ""
  • Преобразовать пустой массив в число0, иди получайtrue, а затем преобразовать в числа, чтобы получить1:+(!(+[])) === 1

По этим правилам мы можем получить искомую строку. Это видно из схемы ниже:

![] + [] === "false"
+!+[] === 1

(![] + [])[3] + (![] + [])[4] + (![] + [])[2] + (![] + [])[0]
^^^^^^^^^^      ^^^^^^^^^^      ^^^^^^^^^^      ^^^^^^^^^^      
  "false"         "false"         "false"         "false"       

^^^^^^^^^^^^^   ^^^^^^^^^^^^^   ^^^^^^^^^^^^^   ^^^^^^^^^^^^^    
      s               e               l               f         

Окончательное выражение таково:

(![] + [])[+!+[]+!+[]+!+[]] + 
(![] + [])[+!+[]+!+[]+!+[]+!+[]] + 
(![] + [])[+!+[]+!+[]] +
(![] + [])[+[]]

После сортировки пробелов и новых строк это строка кода:

(![]+[])[+!+[]+!+[]+!+[]]+(![]+[])[+!+[]+!+[]+!+[]+!+[]]+(![]+[])[+!+[]+!+[]]+(![]+[])[+[]]

Теперь вы должны понять принцип волшебного кода JavaScript? Используйте свое воображение, чтобы увидеть, что еще вы можете написать? Например, сегодня Рождество, приходите «Счастливого Рождества»?

В любом случае, с Рождеством!

Эта статья переведена и организована в соответствии с https://javascript.christmas/2019/17, и в нее добавлен некоторый собственный контент.

Больше галантереи передовых технологий можно найти в общедоступном аккаунте WeChat: станция перевода 1024.

微信公众号:1024译站