> В чем отличие среды исполнения JavaScript в браузере и на сервере (JavaScript)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: YADRO
Стек: JavaScript
> Пример ответа
Короткий ответ
Основное отличие - в окружении и доступных API. В браузере есть DOM, BOM, Web APIs (fetch, setTimeout, event loop с макрозадачами и микрозадачами), а на сервере (Node.js) - модули fs, http, process, работа с файловой системой и отсутствие DOM. Event loop в Node.js дополнен фазами (timers, I/O callbacks, poll, check, close). Также различаются глобальные объекты: window vs globalThis.
Подробное объяснение
Среда исполнения JavaScript в браузере и на сервере (Node.js) имеет принципиальные различия, обусловленные разными задачами: браузер - это клиент для взаимодействия с пользователем, сервер - для обработки запросов и работы с ресурсами.
Глобальные объекты и API:
- Браузер:
window(илиglobalThis),document,navigator,location,history,localStorage,fetch,WebSocket,setTimeout,requestAnimationFrame. - Node.js:
global(илиglobalThis),process,Buffer,require,module.exports,__dirname,__filename,fs,http,path,crypto.
Модульная система:
- Браузер: ES modules (
import/export) через<script type="module">, CommonJS не поддерживается нативно. - Node.js: поддерживает и CommonJS (
require/module.exports), и ES modules (с.mjsили"type": "module"в package.json).
Event loop:
- Браузер: имеет макрозадачи (setTimeout, setInterval, UI rendering) и микрозадачи (Promise, MutationObserver). Очередь микрозадач обрабатывается после каждой макрозадачи.
- Node.js: event loop разделён на фазы: timers, pending callbacks, idle/prepare, poll, check, close callbacks. Микрозадачи обрабатываются между фазами. Также есть
process.nextTick- особая очередь, выполняемая перед микрозадачами.
Потоки и параллелизм:
- Браузер: однопоточный, но использует Web Workers для фоновых задач (без доступа к DOM).
- Node.js: однопоточный для JS, но использует libuv thread pool для I/O операций (fs, crypto), а также Worker Threads для CPU-интенсивных задач.
Безопасность:
- Браузер: изолированная среда (same-origin policy, CORS, Content Security Policy), нет доступа к файловой системе.
- Node.js: полный доступ к файловой системе, сети, процессам, что требует осторожности с уязвимостями (path traversal, command injection).
Разное:
- Браузер: поддерживает
fetchиXMLHttpRequestдля HTTP-запросов,WebSocketдля реального времени. - Node.js:
http/httpsмодули для создания серверов и клиентов,socket.ioдля WebSocket.
На практике
Для frontend-разработчика важно понимать, что код, написанный для браузера, не всегда работает на сервере и наоборот. Например, использование document.querySelector вызовет ошибку в Node.js. При разработке изоморфных (универсальных) приложений (например, Next.js, Nuxt.js) нужно проверять окружение через typeof window !== 'undefined' или использовать globalThis.
Типичные сценарии:
- Серверный рендеринг (SSR): код выполняется на сервере, где нет DOM, поэтому нужно избегать прямых обращений к
windowилиdocument. - API-маршруты в Next.js: выполняются в Node.js, поэтому можно использовать
fsдля чтения файлов, но нельзя использоватьlocalStorage. - Middleware: в браузере нет
process.env, но можно использоватьimport.meta.env(Vite) или переменные окружения через Webpack DefinePlugin.
Инструменты для универсального кода:
globalThis- стандартный способ получить глобальный объект в любом окружении.- Полифиллы (например,
whatwg-fetchдля Node.js). - Условные импорты через динамический
import()или проверкуtypeof.
Пример кода
JAVASCRIPT// Проверка окруженияif (typeof window !== 'undefined' && window.document) {console.log('Running in browser');document.getElementById('app').innerHTML = 'Hello from browser';} else {console.log('Running in Node.js');const fs = require('fs');fs.writeFileSync('log.txt', 'Hello from server');}// Использование globalThisglobalThis.myGlobal = 'accessible everywhere';console.log(globalThis.myGlobal); // работает и в браузере, и в Node.js// Event loop разница// Браузер: setTimeout и PromisesetTimeout(() => console.log('macro'), 0);Promise.resolve().then(() => console.log('micro'));// Вывод: micro, macro// Node.js: process.nextTickprocess.nextTick(() => console.log('nextTick'));setTimeout(() => console.log('timer'), 0);Promise.resolve().then(() => console.log('promise'));// Вывод: nextTick, promise, timer
Как отвечать на собеседовании
Начни с ключевого отличия - окружение и доступные API. Затем перечисли основные различия: глобальные объекты, модульная система, event loop, безопасность. Для senior-уровня важно показать понимание event loop в Node.js (фазы, process.nextTick) и как это влияет на порядок выполнения кода. Приведи пример изоморфного кода и объясни, как избежать ошибок при SSR. Упомяни про globalThis как универсальный глобальный объект. Если спросят про производительность, скажи, что Node.js эффективнее для I/O, а браузер - для UI.
Что проверяет интервьюер
- Глубину понимания сред исполнения, а не просто заученные факты.
- Умение проектировать изоморфный код и избегать платформенных зависимостей.
- Знание event loop в деталях (фазы, микрозадачи, process.nextTick).
- Понимание безопасности и ограничений каждой среды.
- Способность объяснить trade-offs при выборе между браузерным и серверным кодом.
Типичные ошибки
- Утверждение, что Node.js - это фреймворк, а не среда исполнения.
- Игнорирование
process.nextTickи его приоритета. - Путаница между
windowиglobal(в Node.js нетwindow). - Предположение, что
fetchдоступен в Node.js по умолчанию (до версии 18 требовался полифилл). - Использование
requireв браузере без сборщика (Webpack, Vite). - Непонимание, что
setTimeout(fn, 0)в Node.js не гарантирует выполнение сразу после микрозадач из-за фаз event loop.
> Похожие задачи по frontend
Что такое Blob в JavaScript и для чего он используется?
Можно ли получить данные объекта response до преобразования в json в JavaScript
Как сделать приватный метод в JavaScript
Как передаются массивы в JSON
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью