Почему (! + [] + []) Равно 'true', а (false + []) - "false" в Javascript? - PullRequest
0 голосов
/ 14 января 2019

Я смотрю на грамматику ECMA-262 для определения следующего кода ниже:

const v = (! + [] + []);
const c = (false + []);

console.log(v);
console.log(c);

Что за этим стоит?

До сих пор я не нашел ничего полезного, кто-нибудь знает, почему он дает такие результаты или есть ссылки на него?

Ответы [ 3 ]

0 голосов
/ 15 января 2019

Это потому, что когда вы пытаетесь применить оператор к другой структуре данных, JavaScript-движок применяет приведение .

В первом случае, что он делает:

  1. Преобразование first [] в примитив, который выполняется путем вызова метода toString () массива. Метод toString объединяет все значения массива в строку. Если у вас есть что-то вроде (false + [1,2,3]), вы получите: false1,2,3

  2. Второй шаг - привести логическое значение в контексте String

  3. Теперь, когда у нас есть все значения в одной и той же структуре данных, она просто объединит их все

В вашем случае (! + [] + []) оценивается как 'true', длина которого равна 4.

Книга Вы не знаете JS: Типы и грамматика - драгоценный камень для понимания всех этих странных операций, которые делает движок JavaScript.

РЕДАКТИРОВАТЬ : Как подсказывал Феликс Клинг! Оператор играет другую роль в оценке (! + [] + []).

В этом случае происходит следующее:

  • ! + [] оценивается как истинное. Это связано с тем, что ! + [] помещает их в логический контекст, где к [] применяется операция [toNumber] , которая равна 0, а !0 равна true

  • true + [] оценивается как 'true'. Это происходит потому, что при попытке добавить логическое значение с объектом (массив получен из объекта) [toString] операция применяется к обоим элементам.

0 голосов
/ 15 января 2019

На самом деле, чтобы понять, почему вы получаете этот результат, вы должны подумать, как оценивается выражение (т.е. в каком порядке?). Если мы увидим ваше первое выражение:

const v = (! + [] + []);

мы можем видеть, что существует один логический оператор (логическое НЕ !), один унарный оператор (+) и один арифметический оператор, фактически сложение +. Если мы примем во внимание порядок вычисления этого выражения, мы можем написать его так:

const v = ( (!(+[])) + [] );

Теперь первое вычисленное здесь выражение - +[], и из документации оператора унарный плюс вы получите:

Унарный оператор плюс предшествует своему операнду и вычисляет его операнд, но пытается преобразовать его в число, если его еще нет ...

На самом деле предыдущая оценка приводит к 0 (приведение происходит, когда пустой массив приводится к числовому типу), как вы можете проверить в следующем примере:

console.log(+[]);

Итак, теперь выражение сокращено до

const v = ( (!0) + [] );

Снова, читая некоторую документацию этого логического оператора , который вы можете найти:

Возвращает false, если его единственный операнд может быть преобразован в true; в противном случае возвращает true.

Итак, !0 уменьшен до true (другое принуждение происходит, когда число ноль приводится к логическому типу), как вы можете проверить в следующем примере:

console.log(!0);

Теперь у нас есть следующее выражение, где в игру вступает оператор добавление :

const v = ( true + [] );

Оператор сложения создает сумму числовых операндов или конкатенации строк.

В этом случае оператор выполняет конкатенацию строк, поскольку операнды не являются числами. Итак, вот где новое приведение (в основном неявное приведение типов) происходит снова, потому что ему нужно преобразовать оба операнда в строки:

  • true преобразуется в строку "true" с использованием метода toString() типа Boolean .
  • и пустой массив [] преобразуется в пустую строку "" с использованием доступного метода toString() типа Array .

И, наконец, наше выражение сводится к:

const v = "true" + ""; // or simply "true".

const v = (! + [] + []);
console.log("value: " + v, "type: " + typeof(v));

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

0 голосов
/ 14 января 2019

const v = (! + [] + []);
const c = (false + []);

console.log(v);
console.log(c);

Если вы возьмете .length, вы увидите, что результаты: true и false и что они (результаты операций +) являются не массивами, а строками, и true имеет длину 4 символа, а false равен 5.

Используя вашу ссылку выше, похоже, что это как минимум отчасти актуально:

12.7.3 Оператор сложения (+)

ПРИМЕЧАНИЕ Оператор сложения выполняет либо конкатенацию строк, либо числовое сложение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...