1

语境

我注意到有些函数只能用new前缀调用。在没有它的情况下调用时,会抛出错误非法调用。以下是控制台在Image以不同方式调用时如何反应的两个示例。

-> new Image();
<- <img>
-> Image();
<- TypeError: DOM object constructor cannot be called as a function.

更有趣的是,在仔细观察下,这些类型的函数看起来像函数,但它们不是。举个Image例子,该typeof命令表明它Image是一个函数,但它的构造函数却Image暗示它是一个对象。

这与下面的大多数构造函数非常不同。

function Foo(){
    this.identity = 'Bar';
}

该函数Foo可以通过两种方式调用,new Foo()并且Foo(). 这与功能非常不同Image

问题

这个带有函数的动作与Image大多数构造函数有很大的不同。这怎么可能?这就是为什么new前缀必须与 一起使用的原因Image吗?更重要的是,这种功能可以重新创建吗?

4

2 回答 2

4

我认为这是您正在寻找的逻辑,当new关键字不用于创建以下实例时,它会重现异常Foo

function Foo() {
    if (!(this instanceof arguments.callee)) 
        throw new TypeError("DOM object constructor cannot be called as a function.");

    this.identity = 'Bar';
}

根据这篇文章中的一些评论,如果您处于严格模式,则arguments.callee不必使用函数名称:Foo

function Foo() {
    if (!(this instanceof Foo)) 
        throw new TypeError("DOM object constructor cannot be called as a function.");

    this.identity = 'Bar';
}

在此处查看说明情况的演示。

于 2013-04-20T22:42:35.167 回答
2

问题Image在于它是一个宿主对象——这意味着它不需要遵循原生 EcmaScript 对象的严格语义。例如,它可以继承 not 的东西Function.prototype,实现内部的 [[Construct]] 方法而不是 [[Call]] 和类似的东西。

它们由 DOM 指定(请参阅Where are constructors such as, `new Image()` 和 `new Option()`, 已记录?),特别是这里

提供了一个构造函数来创建HTMLImageElement对象(除了来自 DOM 的工厂方法,例如)createElement()当作为构造函数调用时, this 必须返回一个新对象(一个新的 img 元素)。[…]Image(width, height)HTMLImageElement

然而,它实现了特定于浏览器的:例如,Opera 创建图像时new也没有,不会抛出NOT SUPPORTED错误。

于 2013-04-22T12:33:05.430 回答