Почему серия: (!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[ ])[[~!+[]]*~+[]]

внешний интерфейс JavaScript

Это 6-й день моего участия в Gengwen Challenge.Подробности мероприятия смотрите:Обновить вызов

предисловие

Порог входа в интерфейс низкий, просто сделайте несколько шагов, чтобы узнать глубину воды.
Давайте сначала посмотрим на черную технологию, Нани, что это за штука? Если вы вставите ее в браузер и запустите, вы узнаете ответ?

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

Как только вы выполните его, пожалуйста, успокойтесь и позвольте нам приподнять завесу позора.

по фактуСтрока кода JavaScript, которую можно загрузитьОна очень понятная и понятная, но ее также можно дополнить и расширить, поэтому есть эта статья.

приоритет оператора

(!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]В этом принудительном коде используется только () !~ + [] -- *

приоритет

  1. () приоритет 21
  2. [] приоритет 20
  3. -- ~ !+ приоритет 17
  4. * приоритет 15
  5. + приоритет 14

+Нет. Здесь есть два вида, одинунарный положительный знак, одиндобавление.
[]Есть также два, один как массив, другой как метод доступа к члену.

Дополнительные уровни приоритета см. в MDN.приоритет оператора

преобразование типов

Знак минус -, знак умножения *, должен быть математической операцией, поэтому операнд необходимо преобразовать в числовой тип

Знак плюс + может быть конкатенацией строк или математической операцией, поэтому его можно преобразовать в число или строку.

Унарные операции, такие как +[], имеют только один операнд и преобразуются в числовой тип.

Порядок преобразования

  1. попробуйте использовать ToPrimitive, преобразовать в примитивный тип,
  2. Преобразование прошло успешно, возвращаемое значение.
  3. В противном случае вызовите valueOf, если возврат является примитивным типом, верните
  4. В противном случае вызовите toString(), если возвращается тип прототипа, return , иначе сгенерируйте исключение

Добавление некоторых особых случаев

[] + [] // ''
[] + {} // '[object Object]'
{} + [] // 0
({} + []) // '[object Object]'
{} + {} // NaN
({} + {}) // '[object Object][object Object]'

+[]

вотунарный знак плюс
[]не является примитивным типом, вызовите valueOf
[].valueOf() по-прежнему не возвращает примитивный тип
[].toString()вернуть"",
+""результат 0

[] + []

вотобычный плюс
[]Преобразование в строку представляет собой пустую строку, поэтому пустая строка + пустая строка по-прежнему остается пустой строкой.

[] + {}

{}преобразовать в строку[object Object]
[]Преобразовать в пустую строку

пустой +[object Object] = [object Object]

{} + []

{} + []первый в{}будет распознан как кодовый блок и проигнорирован;
+[]процесс преобразования
[]не является примитивным типом, вызовите valueOf
[].valueOf() по-прежнему не возвращает примитивный тип
[].toString()вернуть"",
+""результат 0

({}+[])

({}+[])здесь{} + []выполняется как выражение,
{}наконец преобразовано в "[объект объект]"
[]наконец преобразовано в ""
Добавляется как "[объект объект]"

{} + {}

{}наконец преобразовано в "[объект объект]"
Первый{}будет считаться блоком кода и ничего не делать
+{}Эквивалентно преобразованию «[object object]» в число с возвратом NaN

({} + {})

Это легко понять, потому что()Роль {} используется как переменная для работы.
({} + {}) = [object Object] + [object Object] = [object Object][object Object]

снять, решить

Что ж, подготовив их, мы можем интерпретировать отговорку.Для удобства интерпретации, Расписываю толкование каждого шага, приезжаем, ставим Х вместе, и летим вместе.

const results = [
    '(!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]', 
    // +[] ==> 0
    '(!(~0)+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]',
    // ~0 ==> -1  取反减1
    '(!(-1)+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]',
    // !(-1) ==> false 
    '(false+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]',
    // false+{} ==> "false[object object]"
    '"false[object object]"[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]',
    // +"" ==> 0
    '"false[object object]"[--[~0][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]',
    // ~0 ==> -1
    '"false[object object]"[--[-1][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]',
    // +[] ==> 0
    '"false[object object]"[--[-1][0]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]',
    // +[] ==> 0
    '"false[object object]"[--[-1][0]*[~0] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]',
    // ~0 ==> -1
    '"false[object object]"[--[-1][0]*[-1] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]',
    // --[-1][0] ==> -2
    '"false[object object]"[-2*[-1] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]',
    // [-1] ==> "-1"
    '"false[object object]"[-2*"-1" + ~~!+[]]+({}+[])[[~!+[]]*~+[]]',
    // "-1" ==> 1
    '"false[object object]"[-2*-1 + ~~!+[]]+({}+[])[[~!+[]]*~+[]]',
    // -2*-1 ==> 2
    '"false[object object]"[2 + ~~!+[]]+({}+[])[[~!+[]]*~+[]]',
    // +[] ==> 0
    '"false[object object]"[2 + ~~!0]+({}+[])[[~!+[]]*~+[]]',
    // !0 ==> true
    '"false[object object]"[2 + ~~true]+({}+[])[[~!+[]]*~+[]]',
    // ~true ==> -2
    '"false[object object]"[2 + ~-2]+({}+[])[[~!+[]]*~+[]]',
    // ~-2 ==> 1
    '"false[object object]"[2 + 1]+({}+[])[[~!+[]]*~+[]]',
    // 2+1 ==> 3
    '"false[object object]"[3]+({}+[])[[~!+[]]*~+[]]',
    // "false[object object]"[3] ==> s
    '"s"+({}+[])[[~!+[]]*~+[]]',
    // {} ==> "[object object]"
    '"s"+("[object object]"+[])[[~!+[]]*~+[]]',
    // [] ==> ""  [].toString() 
    '"s"+("[object object]"+"")[[~!+[]]*~+[]]',
    // "[object object]"+""  ==> "[object object]"
    '"s"+"[object object]"[[~!+[]]*~+[]]',
    // +[] ==> 0
    '"s"+"[object object]"[[~!0]*~+[]]',
    // !0 => true
    '"s"+"[object object]"[[~true]*~+[]]',
    // ~true ==> -2
    '"s"+"[object object]"[[-2]*~+[]]',
    // +[] ==> 0
    '"s"+"[object object]"[[-2]*~0]',
    // ~0 ==> -1
    '"s"+"[object object]"[[-2]*-1]',
    // [-2] ==> "-2"
    '"s"+"[object object]"["-2"*-1]',
    // "-2" ==> 2
    '"s"+"[object object]"[-2*-1]',
    // -2*-1 ==> 2
    '"s"+"[object object]"[2]',
    // "[object object]"[2] ==> b
    '"s"+"b"',
    // "s" + "b" ==> "sb"
    '"sb"',
];

results.forEach( (v,i)=>{
    (function(delay){
        setTimeout(function(){
            console.log(Date.now(), eval(v))
        },delay*5)
    })(i)    
})

Вы найдете много «сб», йо, вы действительно видите это, это вы. Ха-ха.

Суммировать

Благодаря этой строке кода у нас есть более глубокое понимание

  1. приоритет оператора
  2. Правила преобразования сложения и вычитания объектов
  3. кодовый блок{}с объектом{}разница

Эти черные технологии программирования на JavaScript, принудительные руководства и высококачественные коды удивят вас.
Строка кода JavaScript, которую можно загрузить
Каково возвращаемое значение {}+[] и []+{} в JS
What is {} + {} in JavaScript?
Есть вопросы об особом использовании круглых скобок () и квадратных скобок [] в JavaScript?
операторы javascript - условные операторы, операторы запятой, присваивания, () и операторы void
JavaScript values: not everything is an object