JavaScript构造函数替代

时间:2011-04-06 16:04:09

标签: javascript

由于无法将new运算符与arguments数组(.call或.apply)一起使用,所以我想知道我是否可以手动完成。

在以下代码中,obj1obj2等效(在ES3中)?

function MyClass(a, b, c) {}

var obj1 = new MyClass(2,3,4)

var tmp = function() {}
tmp.prototype = MyClass.prototype;
var obj2 = new tmp;
obj2.constructor = MyClass;
MyClass.call(obj2, 2,3,4);

- edit1 -

您的回答是否意味着上述代码错误或与对象构造等效?

4 个答案:

答案 0 :(得分:1)

这个怎么样:

var o = new MyClass;
MyClass.apply(o, args);

您创建的对象通过new关键字正确地从原型继承,然后使用您的参数再次在该对象上调用构造函数。

所有这些要求是你的构造函数构造良好,不会在null参数上崩溃,并且在同一个对象上多次调用时没有副作用。当然所有这些条件都是正确的,因为你写了正确的单位,对吗?

如果您添加

,请回答您的实际问题

tmp.prototype.constructor = MyClass

然后是obj1和obj2是“相同的”。

答案 1 :(得分:1)

如果您使用的是ES5,则可以使用Object.create()正确执行此操作:

function MyClass(a) {
    console.log('in constructor with param: ' + a);
    this.foo = a;
}

var a = new MyClass('a');

var b = Object.create(MyClass.prototype);
b.constructor.apply(b, ['b']);

console.log('a.foo = ', a.foo, ', b.foo = ', b.foo);
console.log(b instanceof MyClass);

输出:

in constructor with param: a
in constructor with param: b
a.foo =  a , b.foo =  b
true

参见http://jsfiddle.net/Qjfyt/1/,它显示了构造函数只被调用一次,如预期的那样。

答案 2 :(得分:1)

使用以下语法,您应该能够直接应用/调用构造函数而不需要太多模糊。或者在不使用new运算符的情况下实例化它。

function MyClass(a,b,c){
  if (!(this instanceof MyClass)){
    return new MyClass(a,b,c)
  }
  // to demonstrate the arguments are usable using call/apply
  this.arg1 = a;
  this.arg2 = b;
  this.arg3 = c;
}

var obj2 = MyClass.call(null,1,2,3); // or MyClass.apply(null,[1,2,3])
alert([obj2.arg1,obj2.arg2,obj2.arg3].join(',')); //=> 1,2,3 

答案 3 :(得分:0)

好吧,您可以使用apply并获取一个几乎与使用new实例化的对象一样的对象:

function MyClass(a, b, c) {this.foo = a;}
var a, b = {}, args = [2, 3, 4]; // notice that b is an Object!
a = new MyClass(2,3,4);
MyClass.prototype.constructor.apply(b, [2, 3, 4]);
console.log('a.foo', a.foo, 'b.foo', b.foo);

正如您所见,这些是等效的,但如果您进一步检查:

console.log('b.constructor === a.constructor', b.constructor === a.constructor);

他们没有相同的构造函数。这是因为b最初是“Object”的一个实例,因为它被设置为一个对象文字,并且它被用作应用于MyClass原型构造函数的上下文。他们将拥有相同的属性/方法,所以也许这足以满足您的需求?

编辑:请参阅下面的@Raynos评论。这种技术意味着你会失去使用MyClass.prototype定义的所有内容。