Оператор instanceof - это красивый и элегантный способ проверить тип объекта JavaScript во время выполнения. Он также хорошо работает с TypeScript, позволяя компилятору сужать типы для определенных ветвей кода на основе проверки во время выполнения.

Это также дает вам ощущение ООП, когда переменная peter является экземпляром Man, экземпляром Human и экземпляром Creature заодно.

Uint8Array, который не является Uint8Array

Работая над расширением нашего браузера в IOV, я столкнулся со сценарием, когда я получил элемент типа Uint8Array, но instanceof Uint8Array получил значение false .

Как такое вообще возможно? Объект выглядел точно так же, как любой другой Uint8Array со всеми установленными метаполями. Все очевидные проверки этого объекта прошли успешно, например, глубокая проверка на равенство с другим Uint8Array.

Но этот экземпляр был другим. Что-то было потеряно.

Структурированное клонирование

Алгоритм структурированного клонирования поддерживает некоторые типы объектов из стандартной библиотеки, например, Uint8Array. Хотя цепочка прототипов не проходит и не дублируется., можно использовать instanceof после клонирования объектов с помощью структурированного клона.

Это было протестировано со всеми тремя способами реализации структурированного клонирования, описанными Сурмой в Глубокое копирование в JavaScript. Другой тест показал, что instanceof работает должным образом при передаче Uint8Array, созданного в WebWorker, в скрипт, который породил этого рабочего.

Понимание instanceof

Благодаря T.J. Сообщение Crowder's Stackoverflow , мы знаем, что

obj instanceof F проверяет, находится ли объект, на который ссылается F.prototype, где-нибудь в цепочке прототипов obj. […]

и в этом случае используется относится к идентификатору объекта (как определение в алгоритме [HasInstance]]). Это означает, что instanceof может работать только тогда, когда элемент конструктора экземпляра совпадает с тем, который мы используем для проверки (глобальный объект Uint8Array в нашем примере).

Не все Uint8Arrays одинаковы

Когда объекты клонируются с использованием алгоритма структурированного клонирования, разработчику не видно, какой элемент конструктора используется для создания клона. В большинстве случаев это тот контекст JavaScript, в котором мы выполняем проверку instanceof. Однако бывают случаи, когда объект-конструктор, создавший экземпляр, является другим.

Это происходит, когда расширение браузера обращается к фоновому скрипту расширения через getBackgroundPage:

Если это желаемое поведение или ошибка, необходимо изучить в дальнейших исследованиях. Также неясно, на каких границах JavaScript именно этот эффект проявляется. До сих пор мы узнали, что граница веб-сайта / WebSocket кажется беспроблемной, а граница backgroundscript / foregroundscript в расширениях браузера кажется проблемой, начиная с версии Chrome 75.