使用构造函数应用/调用

时间:2012-01-15 19:10:22

标签: javascript

这是使用apply和使用构造函数调用的适当方法(提供空对象)吗?

var findCats = RegExp.apply({}, ["cats?", "ig"]);
var findDogs = RegExp.call({}, "dogs?", "ig");

我只是有一种潜行的怀疑:

function Foo(a,b,c) { this.a = a; this.b = b; this.c = c; }
var foo = Foo.call({}, "a", "b", "c");

不会与

完全相同
var foo = new Foo("a", "b", "c");

4 个答案:

答案 0 :(得分:1)

你是对的。直接使用构造函数调用/应用是不一样的。

您可以修改构造函数,但测试正在使用的对象是构造函数的实例...

function Foo(a,b,c) { 
    if( !(this instanceof Foo) )
        return new Foo(a,b,c)
    this.a = a; this.b = b; this.c = c; 
}

var findCats = Foo.apply({}, ["a", "b", "c"]);

因此,在构造函数中,如果this不是instanceof Foo,则会调用new Foo(a,b,c)传递参数。

如果要传递未知数量的参数,这当然不会起作用。

DEMO: http://jsfiddle.net/7ss3m/


另一个选项是为刚从Foo返回新对象的构造函数设置零参数行为,然后将.apply()作为单独的调用。

function Foo(a,b,c) { 
    if( arguments.length === 0 )
        return this;
    this.a = a; this.b = b; this.c = c; 
}

var findCats = new Foo; // get the empty Foo object

Foo.apply(findCats, ["a", "b", "c"]); // apply the args separately

DEMO: http://jsfiddle.net/7ss3m/1/

答案 1 :(得分:1)

这不是一回事,本机构造函数通常会有很多魔法,所以即使传递null也有效。

但是使用自定义构造函数:

var foo = Foo.call({}, "a", "b", "c");

Foo被称为普通函数,因此foo将为undefined,因为Foo在作为普通函数调用时不会返回任何内容。即使您在其中添加了return thisfoo也没有Foo.prototype的原型链接。

答案 2 :(得分:0)

此:

var foo = new Foo("a", "b", "c");

几乎与:

相同
var foo = (function() { var obj = {}; Foo.call(obj, "a", "b", "c"); return obj; })();

但不完全是因为一些记账。

答案 3 :(得分:0)

var foo = new Foo("a", "b", "c");

可以写成

var foo = new(Foo, "a", "b", "c");

这意味着您将new实现为

function new(constructor) {
    var o = Object.create(constructor.prototype);
    var ret = o.constructor.call(o, [].slice.call(arguments, 1));
    if (typeof ret !== "number" && 
        typeof ret !== "string" &&
        typeof ret !== "boolean" &&
        ret !== undefined &&
        ret !== null
    ) {
        return ret;
    }
    return o;
}