JavaScript:通常从其类型创建对象并调用其构造函数

时间:2013-03-15 18:57:44

标签: javascript object constructor

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

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

我不认为这很难做到,但我尝试过各种各样的事情,到目前为止才失败。

更新

我已使用我目前所知的最佳解决方案更新了demo plunk,并在代码中包含了一些有关该问题的评论。下面讨论的失败尝试不再存在。这个解决方案要求所有潜在的chold对象都有一个“新的不可知构造函数”,所以它仍然不理想。我们非常欢迎进一步的想法。


我知道这一行是错误的,原因有两个:

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

首先,我认为某种'this'需要传递给调用函数,我不知道它会是什么。

第二个可能是第一个结果,浏览器中报告错误:

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

我认为这应该是可行的,但是从this.childType创建该子对象并传递参数的语法到目前为止都让我失望了。有人能指出这里缺失的脑细胞吗?

5 个答案:

答案 0 :(得分:2)

可能最干净的方法是让Dog'new Agnostic'(参见有效的JavaScript项目33)。注意Dog构造函数现在将如何返回新的Dog,无论您如何调用它。

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

  this.name = name;
  return this;
};

使用'apply'而不是call。

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

虽然看起来对你所有的建造者来说似乎都是一个仪式,但无论如何它实际上是个好主意。我发现自己的大部分对象new都是不可知的。

答案 1 :(得分:1)

newarguments不可知oneliner将如下所示:)

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;
}

答案 2 :(得分: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/

的更多信息

答案 3 :(得分:0)

  

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

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

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

首先,我认为某种'this'需要传递给调用函数,我不知道它会是什么。

是的,call期望某些内容可用作该功能的thisArg。但是,您似乎需要apply,因为您拥有argumens array args

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

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

对于没有Object.create的解决方案,并检查构造函数的返回类型,请参阅Use of .apply() with 'new' operator. Is this possible?

答案 4 :(得分:-1)

正确答案是

var child = new this.childItemType(args);

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