Проблема з спробою з'ясувати, в якому середовищі працює ваш код, полягає в тому, що будь-який об’єкт можна змінювати та оголошувати, що робить його майже неможливим з'ясувати, які об'єкти є природними для середовища, а які були змінені програмою.
Однак є кілька хитрощів, які ми можемо використати, щоб точно зрозуміти, в якому середовищі ти знаходишся.
Давайте почнемо з загальноприйнятого рішення, яке використовується в бібліотеці підкреслення:
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
всередині нього, а потім завантаживши скрипт у межах цього закриття. У цей момент користувач повністю реплікує середовище вузла і, сподіваємось, знає, що вони роблять, і намагається зробити потрібний стиль вузла. Якщо код викликається в тезі сценарію, він все одно буде захищений від будь-яких нових зовнішніх закриттів.