gpt4 book ai didi

javascript - 如何构造 JavaScript 对象(使用 'apply' )?

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:38:51 25 4
gpt4 key购买 nike

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

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

这适用于用 JavaScript 编写的构造函数,但如果我尝试 construct(Date, [...]),它会失败并出现 TypeError。我还不知道是否还有更多此函数无法处理的 native 构造函数。那么我的问题是......

  • 最新版本的 JavaScript (ECMAScript 5) 中是否有函数可以解决我的问题?
  • 如果不能,有什么方法可以检查有问题的构造函数,看是否可以使用上述函数? (如果不能,我可能不得不使用 eval("new "+cname+"("+arglist+")")。)

/乔恩

最佳答案

在 ES5 中,你可以通过 bind 来完成.

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

这是有效的,因为当绑定(bind)函数出现在 new 的右侧时 bind 仍然使用 [[Construct]] 抽象运算符 http://es5.github.com/#x15.3.4.5.2这说

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. 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 实现上,但不能正确处理用作构造函数的绑定(bind)函数,所以如果您不确定自己的代码在真正的 ES5 实现上运行,那么你必须回到 hackery 的三 Angular 形:

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 - 如何构造 JavaScript 对象(使用 'apply' )?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4226646/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com