Вопрос:

Классы ES6: как насчет инстроспекции?

javascript class ecmascript-6 introspection

1557 просмотра

1 ответ

525 Репутация автора

В ES5 я мог проверить существование «класса» (функции конструктора) в объекте окна:

if (window.MyClass) {
... // do something
}

В ES6, согласно этой статье , глобально объявленные классы являются глобальными, а не свойствами глобального объекта ( windowв браузерах):

Но теперь есть и глобальные переменные, которые не являются свойствами глобального объекта. В глобальной области видимости следующие переменные создают следующие объявления:

  • let декларации
  • const декларации
  • Объявления класса

Так что, если я не могу использовать if (window.MyClass), есть ли способ сделать то же самое?

На самом деле есть ли правильный способ сделать это без использования оконного объекта?

Автор: Samuel Maisonneuve Источник Размещён: 19.05.2015 09:25

Ответы (1)


12 плюса

750049 Репутация автора

Решение

В ES5 мы могли бы проверить существование класса в объекте окна

Только если функция конструктора была глобальной, что является плохой практикой.

В ES6, согласно этой статье , глобально объявленные классы являются глобальными, а не свойствами глобального объекта ...

Верный. (То же самое верно letи для constобъявлений в глобальной области видимости.) Это определено в §8.1.1.4: Глобальные записи среды :

Глобальная запись среды логически представляет собой одну запись, но она указывается как составная инкапсуляция объекта записи среды и декларативной записи среды. Объектная запись среды имеет в качестве базового объекта глобальный объект связанной области. Этот глобальный объект является значением, возвращаемым конкретным методом GetThisBinding глобальной записи среды. (Например, глобальный объект, на который ссылается windowбраузер - TJ) Компонент Object Environment Record глобальной записи Environment содержит привязки для всех встроенных глобальных переменных (раздел 18) и все привязки, представленные FunctionDeclaration , GeneratorDeclaration или VariableStatementсодержится в глобальном коде. Привязки для всех других объявлений ECMAScript в глобальном коде содержатся в декларативном компоненте записи среды глобальной записи среды.

(Курсив мой) Так что те вещи , которые используются для перехода на глобальный объект в ES5 и еще раньше делать (плюс генераторы, так как он был бы еще более запутанной , если они не делали), но новые вещи ( let, constи classдекларации) не . Они глобальные, но не свойства глобального объекта.

Вернуться к вашему вопросу ...

Так что, если я не могу использовать if (window.MyClass), есть ли способ сделать то же самое?

Вы могли бы использовать

if (typeof MyClass === "function") {

... поскольку typeofнеразрешимый символ не выбрасывает ReferenceError. Это также имеет преимущество проверки того, MyClassнаходится ли область действия кода, даже если она не глобальная.

Там в Гоча есть , хотя: Если этот код находится в той же области , где MyClassобъявлено через class(или letили const) , но это выше MyClass в этой области видимости, даже typeofчек будет бросать ReferenceError, потому что вы не можете получить доступ к связыванию он создает на всех (не даже с typeof) до class(или letили const).

Например, это бросит:

if (typeof MyClass === "function") {  // ReferenceError here
    // Yup, it's defined
    // ...
}
// ...
class MyClass {
}

Пространство от начала объема к class, letили constлиния называется временной мертвой зоной (ТДЗ) и вы не можете получить доступ к переменному связыванию на всех. Следовательно, вы должны поймать ReferenceError:

let exists = false;
try {
    exists = typeof MyClass === "function";
} catch (e) {
}

На самом деле есть ли правильный способ сделать это без использования оконного объекта?

Пока модули JavaScript не дойдут до широкой поддержки браузера, есть несколько способов:

  1. Используйте некоторую библиотеку определения асинхронного модуля для загрузки ваших модулей. Некоторые примеры: RequireJS, SystemJS, CommonJS

  2. Имейте единственную глобальную переменную, которую вы будете использовать для ссылки на объект, и задайте своим глобальным свойствам приложения этот объект. Вот типичный способ сделать это:

    var MyApp = MyApp || {};
    if (!MyApp.ThisModule) {                  // You can leave this `if` out
                                              // if there's no chance of the file
                                              // being loaded more than once
        MyApp.ThisModule = function(module) {
            module.MyClass = class MyClass {
                // ...class definition here...
            }
        }({});
    }
    

Это также дает вам удобную область (анонимную функцию), в которую можно помещать любые глобальные переменные уровня модуля.

Автор: T.J. Crowder Размещён: 19.05.2015 09:51
Вопросы из категории :
32x32