【问题标题】:Object-Natured Functions对象性质的函数
【发布时间】:2013-04-20 22:04:13
【问题描述】:

上下文

我注意到某些函数只能使用new 前缀调用。在没有它的情况下调用时,会抛出错误 Illegal Invocation。以下是在以不同方式调用 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 一起使用的原因吗?更重要的是,这种功能可以重新创建吗?

【问题讨论】:

  • 我没有仔细研究过这个问题,也没有解决我的问题。我在问为什么有些构造函数需要新的前缀,而另一些则无所谓。有什么不同,我该如何重新创建它?
  • 简单,检查this是否是MyObjfunction MyObj() { if(!(this instanceof MyObj)) throw new TypeError("MyObj must be called as a constructor") }
  • @apsillers:您可以通过以下方式通用(以防函数名称更改):if (!(this instanceof arguments.callee)) throw new Error("Constructor called as a function"); 请参阅here

标签: javascript function object constructor


【解决方案1】:

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

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

    this.identity = 'Bar';
}

根据 this post 中的一些 cmets,如果您处于严格模式,则必须使用函数名称 Foo 而不是 arguments.callee

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

    this.identity = 'Bar';
}

查看说明情况的DEMO here

【讨论】:

  • “如果你不是在严格模式下,你必须使用函数名” - 你的意思是“如果你在严格模式下”
【解决方案2】:

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

它们由 DOM 指定(参见 Where are constructors such as, `new Image()` and `new Option()`, documented?),特别是 here

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

但它实现了特定于浏览器的功能:例如,Opera 创建的图像也没有new,不会引发NOT SUPPORTED 错误。

【讨论】:

    猜你喜欢
    • 2019-02-12
    • 2021-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-20
    • 2013-04-29
    • 2013-10-11
    相关资源
    最近更新 更多