Цепные конструкторы в JavaScript - PullRequest
0 голосов
/ 21 октября 2010

Я пытаюсь реализовать какую-то иерархию классов в JavaScript. я Кажется, я понял цепочку прототипов, но мне все еще нужно разобраться конструктор-цепочка. Следуя Полному руководству Дэвида Фланагана , Я написал

function DerivedClass()
{
    BaseClass.apply(this, arguments);  // chain constructors
    // do some initializations specific to DerivedClass...
}

var foo = new DerivedClass();

, где BaseClass() - моя собственная функция, написанная на C ++ (я используя QtScript ). Моя проблема в том, что тогда, BaseClass() называется как функция, а не как конструктор.

Я мог бы написать BaseClass(), чтобы он всегда вел себя как конструктор, однако это называется. Но я боюсь, что однажды один из моих пользователей забудет new и просто напиши

var bar = BaseClass();

В такой ситуации я бы хотел BaseClass() сделать что-то еще разумнее, чем инициализировать глобальный объект. Например:

if (!context->isCalledAsConstructor()) fail_gracefully();

Но тогда цепочка конструктора терпит неудачу!

Есть ли способ, которым я могу связать конструкторы и получить BaseClass() на самом деле называться конструктором? Или я должен просто обучить своих пользователей никогда не забывать new? Прямо сейчас я испытываю желание заменить тест выше по:

if (context->thisObject().strictlyEquals(engine->globalObject()))
    fail_gracefully();

но мне интересно, есть ли более чистый способ справиться с этим.

Спасибо!

Ответы [ 2 ]

0 голосов
/ 22 октября 2010

Отвечаю сам ...

Я подумал о своей проблеме в одночасье ... и, кажется, нашел несколько более удовлетворительное решение: ведите себя как конструктор, если this является экземпляр колле. Этот тест несколько строже, чем проверка будь то глобальный объект, но он по-прежнему допускает конструктор цепочки, пока прототипы были должным образом соединены.

Вот первые строки моего собственного конструктора (SerialPort это мой базовый класс, построенный вокруг QSerialDevice ):

/*
 * Should we behave as a constructor?
 *
 * We could use context->isCalledAsConstructor() to decide. However,
 * we may want to subclass SerialPort in JavaScript and chain the
 * constructors:
 *
 *      function DerivedClass()
 *      {
 *          SerialPort.apply(this, arguments);
 *          // do some more initializations...
 *      }
 *
 * This would fail if we decided on the basis of
 * context->isCalledAsConstructor(). The test below is somewhat less
 * strict. It allows constructor chaining provided the prototypes
 * have been properly chained.
 */
bool behave_as_constructor =
    context->thisObject().instanceOf(context->callee());

Самое смешное в этом: в отличие от isCalledAsConstructor(), это Тест также может быть реализован в конструкторе JavaScript!

0 голосов
/ 21 октября 2010

Вы должны научить своих пользователей никогда не забывать new.

В конце концов, все «конструкторы» в JavaScript - это просто функции, поэтому вы не можете защитить от вызова конструктора как функции.используя new.Просто потому, что не существует «предупреждения о времени компиляции», как в Java, оно ничем не отличается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...