将参数对象作为参数传递的Javascript对象工厂方法

时间:2016-08-19 16:53:32

标签: javascript

以下代码无法正常工作(jsFiddle):



function makeFoo(a, b) {
  var foo = new Foo();
  Foo.apply(foo, arguments);
  return foo;
}
var Foo = function(a, b) {
  console.log(
    "This should be called once. "+
    "a=\"" + a + "\", " + 
    "b=\"" + b + "\", "
  );
  this.a = a;
  this.b = b;
}
Foo.prototype.go = function() {
  console.log("a: " + this.a);
  console.log("b: " + this.b);
};
var foo = makeFoo("Hello", "World");
foo.go();




预期产出:

  

应该调用一次。 a ="你好",b ="世界"
  a:你好   b:世界

实际输出:

  

应该调用一次。 a =" undefined",b =" undefined"
  这应该被调用一次。 a ="你好",b ="世界"
  a:你好   b:世界

2 个答案:

答案 0 :(得分:6)

这是因为您拨打Foo两次:通过new并通过函数调用。

我认为new Foo()只想创建一个继承自Foo.prototype的对象。为此,请改用Object.create(Foo.prototype)

function makeFoo(a, b) {
  var foo = Object.create(Foo.prototype);
  var result = Foo.apply(foo, arguments);
  return Object(result) === result ? result : foo;
}
var Foo = function(a, b) {
  console.log(
    "This should be called once. "+
    "a=\"" + a + "\", " + 
    "b=\"" + b + "\", "
  );
  this.a = a;
  this.b = b;
}
Foo.prototype.go = function() {
  console.log("a: " + this.a);
  console.log("b: " + this.b);
};
var foo = makeFoo("Hello", "World");
foo.go();

但这只是一个hack,你需要在ECMAScript 5中使用它,因为无法用任意数量的参数实例化一个构造函数。

应该实例化构造函数,而不是作为函数调用。在ECMAScript 6中,您可以使用Reflect.construct

function makeFoo(a, b) {
  return Reflect.construct(Foo, arguments);
}
var Foo = function(a, b) {
  console.log(
    "This should be called once. "+
    "a=\"" + a + "\", " + 
    "b=\"" + b + "\", "
  );
  this.a = a;
  this.b = b;
}
Foo.prototype.go = function() {
  console.log("a: " + this.a);
  console.log("b: " + this.b);
};
var foo = makeFoo("Hello", "World");
foo.go();

答案 1 :(得分:0)

试试这个:

function makeFoo(a, b){
  var foo = new Foo(a,b);
  return foo;
}