0

Мои попытки понять:

console.log(null + {0:1}[0] + [,[1],][1][0]); // 2
console.log(null + {0:1}[0] + [,[2],][1][0]); // 3
console.log(null + {0:1}[0] + [,['2'],][1][0]); // 12

console.log(null + {0:1}[1] + [,[1],][1][0]); // NaN console.log(null + {0:1}[0] + [,[1],][1][1]); // NaN

console.log(null + {0:1}[0] + [,[1],][2][0]); // TypeError: Cannot read property '0' of undefined

  • 1
    ой, может вам лучше спецификацию почитать? Ведь такие непонятные конструкции никто никогда не будет писать в коде, а базовые преобразования написаны в спеке. А то вы сейчас в такие дебри забретаете, а нужно с простого. Например, почему [] + {} === "[object Object]", а {} + [] === 0 – Алексей Шиманский Apr 11 '21 at 07:04
  • 2
    Почему результат выражения null + {0:1}[0] + [,[1],][1][0] равен 2? - потому что null + 1 = 1 и [,[1],][1][0] = 1 – Алексей Шиманский Apr 11 '21 at 07:07

2 Answers2

2

null + {0:1}[0] + [,[1],][1][0]


В арифметических операциях null преобразуется в 0

console.log( null + 5 ); // 5
console.log( 5 + null ); // 5
console.log( 5 * null ); // 0

{0: 1}[0] — Из объекта {0: 1} достается значение свойства "0", т.е. 1.

console.log( {0: 1}[0] ); // 1

let obj = {0: 1}; console.log( obj[0] ); // 1, то же самое.

obj = {a: 1}; console.log( obj['a'] ); // тоже 1. Пусть 0 не запутывает...

console.log( {a: 1}['a'] );


[,[1],][1][0] выполняется слева направо.

[,[1],] — создается массив из двух ячеек, [empty, [1]] (в массиваx и объектах последняя запятая игнорируется)

let arr = [,[1],];

console.log( arr.length ); // 2 console.log( arr[0] ); // undefined console.log( arr[1] ); // [1] ◄*

console.log( [,[1],][1] ); // [1] ◄*

А если [,[1],][1] дает массив [1], получается ( [,[1],][1] )[0][1][0]

Где [1] — массив с одним элементом 1, который находится под индексом 0. Этот элемент и получается при выполнении:

console.log( [1][0] ); // 1

let arr = [1]; console.log( arr[0] ) // 1 (то же самое).

/// console.log( [5, 7, 9][0] ); // 5 console.log( [5, 7, 9][1] ); // 7 console.log( [5, 7, 9][2] ); // 9


null + {0:1}[0] + [,[1],][1][0]
 ↓        ↓          ↓
 0   +    1     +    1          = 2

Ну и, список ваших попыток из вопроса:

null + {0:1}[0] + [,[2],][1][0]); // 3
  0  +    1     +    2

null + {0:1}[0] + [,['2'],][1][0]); // 12 0 + 1 + '2' // это конкатенация со строкой, а не суммирование, получается строка "12"

null + {0:1}[1] + [,[1],][1][0]); // NaN 0 + undefined+ 1 // у объекта {0:1} нет свойства 1 // любая арифметика с undefined дает NaN

null + {0:1}[0] + [,[1],][1][1]); // NaN 0 + 1 + ( [1] )[1] // у массива [1] нет индекса 1, только нулевой 0 + 1 + undefined

null + {0:1}[0] + [,[1],][2][0]); // TypeError: Cannot read property '0' of undefined 0 + 1 + (undefined)[0] // У массива [,[1],] нет [2]-го элемента. undefined

OPTIMUS PRIME
  • 27,121
2

Давай разберем это выражение: null + {0:1}[0] + [,[1],][1][0] null - можно отбросить так как это "ничего", оно приводится к 0.

{0:1} - это объект, у которого по ключу 0 значение 1.

[0] - получение значения по нулевому ключу от объекта, таким образом:

{0:1}[0] - получить значение объекта {0:1} по ключу 0. Это значение равно 1.

Идем дальше, разберем [,[1],][1][0].

[,[1],] - это массив, нулевое значение перед запятой будет пустым (<1 empty item>), первое значение равно [1] и является вложенным массивом, нулевое значение которого равно 1. Т.е. весь этот массив можно представить так - [ <1 empty item>, [ 1 ] ] Далее [1][0] - взять первое значение исходного массива и взять нулевое значение вложенного массива т.е. выражение [,[1],][1][0] будет равно [1][0], где [1] - вложенный массив, нулевое значение которого равно 1.

Таким образом значение [,[1],][1][0] = 1. Итого получаем null + {0:1}[0] + [,[1],][1][0] = 1 + 1 = 2

  • 1
    [undefined, [1], undefined] — не совсем так (можете проверить, что выдаёт [,[1],] в консоли). Последняя запятая игнорируется, так что третьего элемента вообще не будет. А на месте первого будет дырка (hole), там не будет даже undefined. Это отличие важно, так как при переборах элементов массива часто бывает так, что undefined вызывает срабатывание итерации, а дырка не вызывает. Подробнее см. https://exploringjs.com/impatient-js/ch_arrays.html#array-holes – vsemozhebuty Apr 11 '21 at 08:28
  • 1
    Да, вы правы, сейчас проверил действительно будет [ <1 empty item>, [ 1 ] ]. Исправил ответ – Alexander Parshin Apr 11 '21 at 12:10