用JavaScript链接构造函数

时间:2010-10-21 12:31:59

标签: javascript qtscript constructor-chaining

我正在尝试在JavaScript中实现某种类层次结构。一世 我想我理解了原型链,但我还是要理清它 构造函数链。继David Flanagan的Definitive Guide之后, 我写了

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 :(得分:0)

您应该教育您的用户永远不要忘记new

JavaScript中的所有“构造函数”毕竟只是函数,因此无法防止构造函数被调用为函数。

在不使用new的情况下尝试创建新对象的JavaScript不正确。正因为Java中没有“编译时警告”,所以没有任何不同。

答案 1 :(得分:0)

回答自己...

我一夜之间想到了我的问题......我想我发现了一些问题 更令人满意的解决方案:如果this是一个,则表现为构造函数 calle的一个例子。这个测试比检查更严格 它是否不是全局对象,但它仍然允许构造函数 链接,只要原型已被正确链接。

以下是我的原生构造函数的第一行(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()不同,这个 test也可以在JavaScript构造函数中实现!