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