интервью Ватерлоо
Однажды я пошел на собеседование и столкнулся с таким вопросом:
[]+[]
{}+{}
1+[]
???WTF, кто будет писать такой код, когда все в порядке, ну, я был не прав, не бейте меня. Что вы собираетесь делать после оглушения? Конечно, мне нужно выучить волну, поэтому я искал информацию по всему миру. Конечно, я должен поделиться волной хороших вещей. Что ж, давайте вместе погрузимся в мир неявного преобразования JavaScript.
операция сложения
Правила операции сложения в JavaScript очень просты, он выполняет только сложение чисел и строк, а все те, которые не относятся к этим двум типам, будут преобразованы в эти два примитивных типа данных и затем обработаны.
В JavaScript существует два типа типов данных:
- Примитивы: undefined, null, boolean, число, строка, символ
- Все остальное является объектом, включая массивы и функции.
Так как же объекты преобразуются в примитивные типы данных? Не паникуйте, мы продолжим наблюдать.
ToPrimitive
JS имеет внутреннюю операциюToPrimitive()
, который используется для преобразования объектов в примитивные типы данных.
ToPrimitive(input, PreferredType?)
Эта функция принимает два параметра:
- input:Этот параметр является значением входа.
- PreferredType:Этот параметр может быть числом или строкой, который представляет, в какой примитивный тип данных наш объект будет преобразован первым. Если этот параметр отсутствует, по умолчанию он принимает значение String для экземпляров Date и Number для остальных. Шаги преобразования также будут различаться в зависимости от этого параметра.
Давайте посмотрим на процесс конвертации для разных параметров.
PreferredType — это число
- Если input является примитивным типом, верните input напрямую.
- В противном случае, если ввод является объектом, объект
valueOf()
метод и возвращается напрямую, если результат является примитивным типом. - Если объект, возвращенный на предыдущем шаге, все еще является объектом, вернитесь к вызову объекта.
toString()
метод, который возвращается, если результат является примитивным типом данных. - Выдает ошибку, если это не примитивный тип данных, обычноUncaught TypeError: Cannot convert object to primitive value.
PreferredType — это строка
Параметр String не будет уточняться.Когда параметр String, второй и третий шаги выше могут быть заменены местами, то есть первый вызовtoString()
Повторное использованиеvalueOf()
.
+ операция
value1 + value2
Вышеупомянутое работает следующим образом:
- Преобразуйте оба операнда в примитивные типы данных:
// PreferredType被省略,因此非日期为 Number,日期为 String。
prim1 = ToPrimitive(value1)
prim2 = ToPrimitive(value2)
- Если prim1 или prim2 является строкой, преобразуйте ее в строку и верните конкатенацию результатов.
- В противном случае преобразуйте как 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
а также+[]
, поэтому получен вышеуказанный результат.
Суммировать
Ну, после вышеизложенного исследования, я полагаю, что все не будут поставлены в тупик этими проблемами, но помните, что {} может привести к другим результатам из-за различий браузера в предыдущем случае.Конечно, если вы таким образом, не будет проблема в обертывании {} с () или объявлении его использования в первую очередь.
больше ресурсов
- What is {} + {} in JavaScript?—— Автор имеет звание Руан Ифэн из Германии
больше статеймой репозиторий блога, если читатели сочтут это полезным, добро пожаловать в звездочку, буду признателен.