Непонятный []+{} в нишевом фронтенд-интервью

внешний интерфейс JavaScript модульный тест опрос

интервью Ватерлоо

Однажды я пошел на собеседование и столкнулся с таким вопросом:

[]+[]
{}+{}
1+[]

???WTF, кто будет писать такой код, когда все в порядке, ну, я был не прав, не бейте меня. Что вы собираетесь делать после оглушения? Конечно, мне нужно выучить волну, поэтому я искал информацию по всему миру. Конечно, я должен поделиться волной хороших вещей. Что ж, давайте вместе погрузимся в мир неявного преобразования JavaScript.

операция сложения

Правила операции сложения в JavaScript очень просты, он выполняет только сложение чисел и строк, а все те, которые не относятся к этим двум типам, будут преобразованы в эти два примитивных типа данных и затем обработаны.

В JavaScript существует два типа типов данных:

  • Примитивы: undefined, null, boolean, число, строка, символ
  • Все остальное является объектом, включая массивы и функции.

Так как же объекты преобразуются в примитивные типы данных? Не паникуйте, мы продолжим наблюдать.

ToPrimitive

JS имеет внутреннюю операциюToPrimitive(), который используется для преобразования объектов в примитивные типы данных.

ToPrimitive(input, PreferredType?)

Эта функция принимает два параметра:

  • input:Этот параметр является значением входа.
  • PreferredType:Этот параметр может быть числом или строкой, который представляет, в какой примитивный тип данных наш объект будет преобразован первым. Если этот параметр отсутствует, по умолчанию он принимает значение String для экземпляров Date и Number для остальных. Шаги преобразования также будут различаться в зависимости от этого параметра.

Давайте посмотрим на процесс конвертации для разных параметров.

PreferredType — это число

  1. Если input является примитивным типом, верните input напрямую.
  2. В противном случае, если ввод является объектом, объектvalueOf()метод и возвращается напрямую, если результат является примитивным типом.
  3. Если объект, возвращенный на предыдущем шаге, все еще является объектом, вернитесь к вызову объекта.toString()метод, который возвращается, если результат является примитивным типом данных.
  4. Выдает ошибку, если это не примитивный тип данных, обычноUncaught TypeError: Cannot convert object to primitive value.

PreferredType — это строка

Параметр String не будет уточняться.Когда параметр String, второй и третий шаги выше могут быть заменены местами, то есть первый вызовtoString()Повторное использованиеvalueOf().

+ операция

value1 + value2

Вышеупомянутое работает следующим образом:

  1. Преобразуйте оба операнда в примитивные типы данных:
 // PreferredType被省略,因此非日期为 Number,日期为 String。
prim1 = ToPrimitive(value1)
prim2 = ToPrimitive(value2)
  1. Если prim1 или prim2 является строкой, преобразуйте ее в строку и верните конкатенацию результатов.
  2. В противном случае преобразуйте как prim1, так и prim2 в числа и верните сумму результатов.

значениеOf и toString

Эти два свойства Object, которые вы можете определить сами.Теперь нас это не волнует, давайте посмотрим, что возвращают эти два метода в следующих ситуациях.

// 对象
const a1 = {
  a: 1
};
console.log(a1.valueOf());
console.log(a1.toString());
// 数组
const a2 = [1,2,3];
console.log(a2.valueOf());
console.log(a2.toString());
// 方法
const a3 = function() {
  const a = 1;
  return 1;
};
console.log(a3.valueOf());
console.log(a3.toString());

Поместите приведенный выше код в консоль и распечатайте его:

  • Объект: valueOf() возвращает сам объект, toString() возвращает значение [object Object].
  • Массив: valueOf() возвращает сам объект, массив перезаписывается в String(), а возвращаемое значение эквивалентно использованиюjoin(',')возвращаемое значение, например[1,2,3].toString()Возвращает "1,2,3".
  • Метод: Valueof() возвращает сам метод, а функция также переписала TOString() объекта, который преобразует код в строковое значение, а затем возвращает.

взять каштан

Что ж, судя по тому, что мы сказали выше, эти вопросы на собеседовании просто поливают водой, давайте посмотрим.

[]+{}

Как мы это анализируем? Здесь мы сначала преобразуем [] и {} в примитивные типы данных, а именно ToPrimitive([]) и ToPrimitive({}).PreferredType по умолчанию имеет значение Number, очевидно.[].valueOf()все еще объект, поэтому мы продолжаем,[].toString()В результате получается "", тот же процесс синтаксического анализа {} преобразуется в "[object Object]".

Ну, теперь выражение "" + "[object Object]", мы знаем, что операция + объединяет операнды, пока есть строка, поэтому результатом является "[object Object]".

Однако при тестировании я обнаружил несколько особых случаев,{}+1,{}+[]Результат, напечатанный на консоли этих двух примеров, будет1а также"", очень странно, правда? Я искал информацию и обнаружил, что разные браузеры анализируют ее по-разному. Он рассматривает предыдущий {} как блок кода, поэтому приведенная выше формула становится+1а также+[], поэтому получен вышеуказанный результат.

Суммировать

Ну, после вышеизложенного исследования, я полагаю, что все не будут поставлены в тупик этими проблемами, но помните, что {} может привести к другим результатам из-за различий браузера в предыдущем случае.Конечно, если вы таким образом, не будет проблема в обертывании {} с () или объявлении его использования в первую очередь.

больше ресурсов

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