1

Foo我在名为创建对象的 js 中有一个“类”(函数) 。由于它使用非常频繁,我希望它避免在new要创建它的新实例时要求使用键盘:Foo(something);而不是new Foo(something);.

我让它在 Firefox 中工作:

function Foo(arg) {
    if (this instanceof Window)
        return new Foo(arg);

    //Object construction here.
    this.bar = "Hello " + arg;
}

现在我可以通过将其作为函数调用来创建 Foo 的实例。

console.log(Foo("World").bar); //Output "Hello World" in console.

虽然这在 FF 中有效,但在 Chrome 中却没有,我还不敢测试 IE。

chrome 的问题是它window确实是DOMWindowchrome的类型

Uncaught ReferenceError: Window is not defined

并且this instanceof DOMWindow在 chrome 中不起作用,因为由于某种原因它给出了:

ReferenceError: DOMWindow is not defined

我也尝试过使用!(this instanceof Foo)并且typeof this似乎总是给予"object".

在所有浏览器上调用时,如何可靠地检测new关键字是否被省略?Foo

更新:!(this instanceof Foo)确实有效,我只是return this在我的实际Foo功能中迷路了。

4

4 回答 4

2

我没有测试过,但也许这样的东西会起作用?

var realWindow = this;

function Foo(arg) {
    if (this === realWindow)
        return new Foo(arg);

    //Object construction here.
    this.bar = "Hello " + arg;
}

当然,您需要确保realWindow在任何范围之外声明,以避免可能与this.

不过总的来说,虽然这聪明,但我不建议仅仅为了节省一些打字字符而这样做。它混淆了未来开发人员的代码,通常不是好的做法。

于 2012-05-07T20:55:49.580 回答
2

在 Chrome 20、FF 12 和 IE 8 中测试这是一个 Foo 实例,并且应该可以正常工作:

function Foo(arg) {
    if (!(this instanceof Foo)) return new Foo(arg);

    //Object construction here.
    this.bar = "Hello " + arg;
}

var foo = Foo('World');
var baz = new Foo('Baz');

console.log(foo.bar);
console.log(baz.bar);

作为小提琴:http: //jsfiddle.net/YSEFK/

于 2012-05-07T20:59:37.410 回答
1

反转条件呢?

function Foo(arg) {
    if (!(this instanceof Foo))
        return new Foo(arg);

    //Object construction here.
    this.bar = "Hello " + arg;
}
于 2012-05-07T21:01:25.040 回答
0

你应该这样做的方式是检查当前实例与它自己的类型:

function Foo(...args...) {
    if (!(this instanceof Foo)) {
        return new Foo(...args...);
    }
    ...do stuff...
}

它可以避免尝试检查全局对象,并且几乎可以在任何情况下工作(尽管在其他情况下可能没有意义):

var a = {};
Foo.call(a);

这应该返回什么?在我的示例中,它将返回一个新Foo实例,尽管您可能希望它创建一个新的Foo.

于 2012-05-07T21:01:09.827 回答