0

JavaScript である種のクラス階層を実装しようとしています。プロトタイプ チェーンは理解できたと思いますが、コンストラクター チェーンを整理する必要があります。David Flanagan's Definitive Guideに従って、私は書きました

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

var foo = new DerivedClass();

whereBaseClass()は C++ で記述された私のネイティブ関数です (私はQtScriptを使用しています)。私の問題はBaseClass()、コンストラクターとしてではなく、関数として呼び出されることです。

BaseClass()常にコンストラクターとして動作するようにコーディングできますが、呼び出されます。しかし、いつの日かユーザーの 1 人が忘れnew て書き込んでしまうのではないかと心配しています。

var bar = BaseClass();

このような状況ではBaseClass()、グローバル オブジェクトを初期化するよりも賢明なことをしたいと思います。例えば:

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

しかし、コンストラクターの連鎖は失敗します!

コンストラクターをチェーンして、BaseClass() 実際にコンストラクターとして呼び出す方法はありますか? それとも、決して忘れないようにユーザーを教育する必要がありnewますか? 現在、上記のテストを次のように置き換えたいと思っています。

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

しかし、これを処理するためのよりクリーンな方法があるのだろうか。

ありがとう!

4

2 に答える 2

0

を決して忘れないようにユーザーを教育する必要がありますnew

JavaScript のすべての「コンストラクター」は結局のところ単なる関数であるため、コンストラクターが関数として呼び出されるのを防ぐことはできません。

を使用せずに新しいオブジェクトを作成しようとするのは、正しくない JavaScriptnewです。Javaにあるような「コンパイル時の警告」がないからといって、違いはありません。

于 2010-10-21T12:40:04.323 に答える
0

自分で答える...

私は自分の問題について一晩考えました...そして、もう少し満足のいく解決策を見つけたと思いますthis. このテストは、それがグローバル オブジェクトではないかどうかをチェックするよりも多少厳密ですが、プロトタイプが適切に連鎖されている限り、コンストラクタの連鎖は許可されます。

これが私のネイティブ コンストラクターの最初の行です (これはQSerialDeviceSerialPortを中心に構築された私の基本クラスです):

/*
 * 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 コンストラクターでも実装できます。

于 2010-10-22T12:29:40.933 に答える