Проблема с попыткой выяснить, в какой среде работает ваш код, заключается в том, что любой объект может быть изменен и объявлен, что делает практически невозможным выяснение того, какие объекты являются естественными для среды, а какие были изменены программой..
Однако есть несколько приемов, которые мы можем использовать, чтобы точно определить, в какой среде вы находитесь.
Давайте начнем с общепринятого решения, которое используется в библиотеке подчеркивания:
typeof module !== 'undefined' && module.exports
Этот метод на самом деле идеально подходит для серверной стороны, так как при вызове функции require
он сбрасывает объект this
в пустой объект и переопределяет module
для вас снова, что означает, что вам не нужно беспокоиться о каких-либо внешних вмешательствах.Пока ваш код загружен с помощью require
, вы в безопасности.
Однако в браузере это не работает, так как любой может легко определить module
, чтобы он выглядел как объект, которым вы являетесьнаходясь в поиске.С одной стороны, это может быть желаемое поведение, но оно также определяет, какие переменные пользователь библиотеки может использовать в глобальной области видимости.Может быть, кто-то хочет использовать переменную с именем module
, в которой есть exports
, для другого использования.Это маловероятно, но кто мы такие, чтобы судить, какие переменные может использовать кто-то другой, просто потому, что другое имя использует эту переменную?
Однако хитрость в том, что если мы предполагаем, что ваш скрипт загружается в глобальныйОбласть (которая будет, если она загружена через тег script), переменная не может быть зарезервирована во внешнем закрытии, потому что браузер не позволяет этого.Теперь запомните в узле, объект this
является пустым объектом, но переменная module
все еще доступна.Это потому, что он объявлен во внешнем закрытии.Таким образом, мы можем исправить проверку подчеркивания, добавив дополнительную проверку:
this.module !== module
При этом, если кто-то объявит module
в глобальной области видимости в браузере, он будет помещен вобъект this
, который приведет к сбою теста, поскольку this.module
будет тем же объектом, что и модуль.На узле this.module
не существует, а module
существует во внешнем замыкании, поэтому проверка будет успешной, поскольку они не эквивалентны.
Таким образом, окончательный тест:
typeof module !== 'undefined' && this.module !== module
Примечание. Хотя теперь это позволяет свободно использовать переменную module
в глобальной области действия, все еще возможно обойти это в браузере, создав новое закрытие и объявив module
в этом, затем загружая скрипт в этом замыкании.В этот момент пользователь полностью реплицирует среду узла и, надеюсь, знает, что он делает, и пытается выполнить требования стиля узла.Если код вызывается в теге скрипта, он все равно будет защищен от любых новых внешних замыканий.