如何构造JavaScript对象(使用'apply')? [英] How to construct JavaScript object (using 'apply')?

查看:154
本文介绍了如何构造JavaScript对象(使用'apply')?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种基于(a)构造函数的名称和(b)包含参数的数组来构造任意JavaScript对象的方法。我在stackoverflow的另一个线程中发现了这个函数(由Matthew Crumley?):

I'm looking for a way to construct arbitrary JavaScript objects based on (a) the name of the constructor, and (b) an array containing the arguments. I found this function (by Matthew Crumley ?) in an other thread on stackoverflow:

function construct(constructor, args) {
  function F() { return constructor.apply(this, args); }
  F.prototype = constructor.prototype;
  return new F();
}

这适用于用JavaScript编写的构造函数,我尝试构造(Date,[...])。我还不知道如果有更多的本机构造函数,这个函数不能处理。

This works well with constructors written in JavaScript, but it fails with a TypeError if I try construct(Date, [...]). I don't know yet if there are more native constructors that this function can't handle. My questions are then ...


  • 更新版本的JavaScript(ECMAScript 5)中是否有函数可以解决我的问题? li>
  • 如果没有,是否有一些方法,我可以检查的问题的构造函数,看看是否可以使用上述函数? (如果不能,我可能需要使用eval(new+ cname +(+ arglist +))。)

/ Jon

推荐答案

在ES5中,您可以通过 bind

In ES5, you can do it via bind.

function construct(constructor, args) {
  return new (constructor.bind.apply(constructor, [null].concat(args)));
}

这是因为 bind new 每个 http://es5.github.com/#x15.3.4.5.2


15.3.4.5.2 [[Construct]]



当一个函数对象的[[Construct]]内部方法,使用参数ExtraArgs的列表调用 bind 函数,执行以下步骤:

15.3.4.5.2 [[Construct]]

When the [[Construct]] internal method of a function object, F that was created using the bind function is called with a list of arguments ExtraArgs, the following steps are taken:


  1. 让target为F的[[TargetFunction]]内部属性的值。

  2. 如果目标没有[[Construct]]内部方法,则抛出TypeError异常。 li>
  3. 让boundArgs是F的[[BoundArgs]]内部属性的值。

  4. 让args是一个包含与列表boundArgs相同的值的新列表

  5. 返回调用目标的[[Construct]]内部方法的结果,提供args作为参数。
  1. Let target be the value of F’s [[TargetFunction]] internal property.
  2. If target has no [[Construct]] internal method, a TypeError exception is thrown.
  3. Let boundArgs be the value of F’s [[BoundArgs]] internal property.
  4. Let args be a new list containing the same values as the list boundArgs in the same order followed by the same values as the list ExtraArgs in the same order.
  5. Return the result of calling the [[Construct]] internal method of target providing args as the arguments.


但是大多数实现 Function.prototype.bind 试图将语言特性后端到ES3实现没有正确地处理用作构造函数的绑定函数,所以如果你不确定你的代码是在真正的ES5实现上运行,那么你必须回到三角形的hackery:

but most implementations of Function.prototype.bind that attempt to back-port the language feature onto ES3 implementations do not correctly handle bound functions used as a constructor, so if you're not sure your code is running on a real ES5 implementation then you have to fall back to the triangle of hackery:

function applyCtor(ctor, args) {
  // Triangle of hackery which handles host object constructors and intrinsics.
  // Warning: The goggles! They do nothing!
  switch (args.length) {
    case 0: return new ctor;
    case 1: return new ctor(args[0]);
    case 2: return new ctor(args[0], args[1]);
    case 3: return new ctor(args[0], args[1], args[2]);
    case 4: return new ctor(args[0], args[1], args[2], args[3]);
    case 5: return new ctor(args[0], args[1], args[2], args[3], args[4]);
    case 6: return new ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
    case 7: return new ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
    case 8: return new ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
    case 9: return new ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
    case 10: return new ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);
    case 11: return new ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10]);
    case 12: return new ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11]);
  }
  // End triangle of hackery

  // Create a throwaway subclass of ctor whose constructor does nothing.
  function TemporarySubclass() {}
  TemporarySubclass.prototype = ctor.prototype;
  var instance = new TemporarySubclass();
  instance.constructor = ctor;  // Patch constructor property
  // Run the constructor.  This assumes that [[Call]] internal method is the same as
  // [[Construct]].  It might work with some builtins/host objects where "new` would not.
  var returnValue = ctor.apply(instance, args);
  // If the constructor returned a non-primitive value, return it instead.
  switch (typeof returnValue) {
    case 'object':
      // If ctor is Array, it reaches here so we don't use broken Array subclass.
      // Ditto for Date.
      if (returnValue) { return returnValue; }
      break;
    case 'function':
      return returnValue;
  }
  // Return the constructed instance.
  return instance;
}

这篇关于如何构造JavaScript对象(使用'apply')?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆