1

假设有一个带有 childType 属性的 JavaScript 对象,它是一个对象构造函数,并且您想编写一个通用的 addChild 方法。它需要创建 this.childType 的实例,并调用它的构造函数,将传入的任何参数传递给 addChild。

需要明确的是,重点是每个集合自己创建子对象,使用继承的泛型 addChild 方法及其已知的 childType,而不是验证传入的子对象的类型。

我不认为这很难做到,但我尝试了各种方法,但到目前为止都失败了。

更新:

我已经用迄今为止我所知道的最佳解决方案更新了演示 plunk ,并在代码中包含了一些关于该问题的评论。下面讨论的失败尝试不再存在。此解决方案要求所有潜在的 chold 对象都具有“新的不可知论构造函数”,因此仍然不理想。进一步的想法是最受欢迎的。


我知道这条线是错误的,有两个原因:

var child = new this.childItemType.call(args);

首先是我认为需要将某种“this”传递给调用函数,但我看不出它会在那里。

第二个大概是第一个的结果,浏览器报错:

Uncaught TypeError: function call() { [native code] } is not a constructor

我认为这应该是可行的,但是到目前为止,从 this.childType 和传递的参数创建该子对象的语法让我无法理解。有人可以在这里指出丢失的脑细胞吗?

4

5 回答 5

2

可能最简洁的方法是让 Dog ' newAgnostic'(参见 Effective JavaScript Item 33)。注意Dog构造函数现在将如何返回一个新Dog的,不管你如何调用它。

var Dog = function (name)
{
  if(!(this instanceof Dog)){
    return new Dog(name);
  }

  this.name = name;
  return this;
};

并使用“应用”而不是调用。

var child = this.childItemType.apply(null,arguments);

虽然对于所有构造函数来说这似乎有点仪式感,但无论如何这实际上是一个不错的主意。我发现自己让我的大部分对象都是new不可知的。

于 2013-03-18T13:24:51.300 回答
1

而且不可知newargumentsoneliner看起来像这样:)

var Dog = function( name ) {
    if ( !(this instanceof Dog) ) { return new (Dog.bind.apply( Dog, [null].concat( Array.prototype.slice.apply( arguments ) ) )); }

    this.name = name;

    return this;
}
于 2014-05-14T15:00:37.473 回答
0

你可以试试Object.create(); http://plnkr.co/edit/KjqQfev1k42bH0jAUrrA?p=preview

var child = Object.create(this.childItemType,props);

这会改变您的结构,但它使您不必编写弹性构造函数方法。另请注意,您将原型作为childItemType

Collection.call(this, Dog.prototype);

而不是将参数传递给子对象的构造函数,而是传递一个属性对象:

smiths.addChild({name:{value:'Rover'}});

属性对象是这里的权衡。有关 Object.create 和“第二个参数”的更多信息http://dailyjs.com/2012/06/04/js101-object-create/

于 2013-03-16T00:45:21.330 回答
0

var child = new this.childItemType.call(args);

不,这确实试图Function.prototype.call用作构造函数(正如异常消息告诉你的那样)。但是,根本没有理由使用call

var child = new this.childItemType(arg, arg2, …);

首先是我认为需要将某种“this”传递给调用函数,但我看不出它会在那里。

是的,call期望某些东西被用作thisArg函数。然而,你似乎想要apply一个argumens 数组 args

那么构造函数应用于什么?这是新的实例——就像new操作员那样。所以为了模仿它,我们会使用

var child = Object.create(this.childItemType.prototype);
this.childItemType.apply(child, args);

对于不使用Object.create构造函数并检查构造函数的返回类型的解决方案,请参阅使用 .apply() 和 'new' 运算符。这可能吗?.

于 2013-03-17T14:11:37.220 回答
-1

正确答案是

var child = new this.childItemType(args);

当您想在 javascript 中创建类/函数的对象时,您可以直接执行new ClassName(arguments),调用和应用通常用于调用具有不同范围的类/函数的任何方法

于 2013-03-15T19:14:04.533 回答