在 JavaScript 中绑定/应用构造函数
binding/applying constructors in JavaScript
我一直在寻找使用任意数量的参数调用Javascript构造函数的解决方案,并找到了一些很好的SO帖子,这让我相信这三个调用应该工作相同。 然而,至少在犀牛和节点.js中,它们不会:
1. f = Date.bind(Date, 2000,0,1)
2. g = Date.bind.call(Date, 2000, 0, 1)
3. h = Date.bind.apply(Date, [2000, 0, 1])
第一个具有预期的结果:
print(new f()) //=> Sat Jan 01 2000 00:00:00 GMT-0500 (EST)
但另外两个没有:
print(new g()) //=> Thu Feb 01 1900 00:00:00 GMT-0500 (EST)
print(new h()) //=> Wed Jun 01 1904 00:00:00 GMT-0400 (EST)
所以有些地方出了问题。 有什么想法? 将apply
、bind
和/或call
与new
混合在一起只是一个坏主意吗?
之前接受的答案是不正确的。你可以使用绑定,调用和应用构造函数来创建新的构造函数 - 测试中唯一的问题是你忘记了bind.apply和bind.call正在应用和调用bind,而不是构造函数本身,所以你给出了错误的参数。
f = Date.bind(null, 2000,0,1)
g = Function.bind.call(Date, null, 2000, 0, 1)
h = Function.bind.apply(Date, [ null, 2000, 0, 1 ])
new f() //=> Sat Jan 01 2000 00:00:00 GMT-0500 (EST)
new g() //=> Sat Jan 01 2000 00:00:00 GMT-0500 (EST)
new h() //=> Sat Jan 01 2000 00:00:00 GMT-0500 (EST)
这三个都instanceof
日期。
调用的参数是执行上下文,后跟要应用的参数。Apply 的参数是执行上下文和参数数组。绑定的参数是执行上下文,后跟要绑定的参数。
因此,例如,要应用的参数是要应用绑定的上下文(Date(,后跟一个数组,该数组是绑定的参数(因此第一个数组成员是绑定的上下文参数(。这就是为什么调用或应用绑定令人困惑的原因;为两者提供上下文参数感觉很奇怪。
请注意,当与构造函数一起使用绑定时,上下文参数始终被忽略,因为"new"显式创建新上下文。当上下文参数与保持清晰无关时,我使用 null,但它可以是任何东西。
同时,在这些示例中,应用和调用确实需要知道它们要应用/调用绑定的上下文是 Date 函数。我在可能的情况下将"日期"切换为"功能",以帮助阐明实际提供上下文的内容。当我们在 Date.bind 上调用 apply 或调用时,我们实际上是在调用 apply 或调用未附加到 Date 对象的绑定方法。在这种情况下,绑定方法可以来自任何函数。它可以是 Number.bind.call(Date, null, 2000, 0, 1(,结果将完全相同。
如果原因不明显,请考虑以下示例之间的差异:
context.method();
和
var noLongerAMethod = context.method;
noLongerAMethod();
在第二种情况下,该方法已脱离其原始上下文(...除非它以前被绑定(,如果它在内部依赖于"this",则行为会有所不同。当我们把任何给定函数的绑定作为属性拉取时,而不是直接执行它,它只是指向 Function.prototype 上泛型绑定方法的另一个指针。
就我个人而言,我认为我不需要调用或应用 bind,并且很难想象它会是一个很好的解决方案,但是绑定构造函数以创建新构造函数是我发现非常有用的东西有时非常有用。无论如何,这是一个有趣的谜题。
bind
和 apply
/call
只适用于函数而不是构造函数的调用,所以基本上使用本机方法你不能这样做,一种方法是编写一个bindConstruct
方法,但它可能涉及额外的复杂性:
function bindConstruct(fn) {
// since constructor always accepts a static this value
// so bindConstruct cannot specify this
var extraArgs = [].slice.call(arguments, 1);
// create a 'subclass' of fn
function sub() {
var args = extraArgs.concat([].slice.call(arguments));
fn.apply(this, args);
}
sub.prototype = fn.prototype;
sub.prototype.constructor = sub;
return sub;
}
这实际上为您的构造函数创建了一个子类。
然后你的代码:
var MyClass = function(x, y) {
console.log(arguments);
console.log(x + y);
}
var BindedMyClass = bindConstruct(MyClass, 1, 2, 3);
var c = new BindedMyClass(4, 5);
console.log(c instanceof MyClass);
console.log(c instanceof BindedMyClass);
您也可以将此函数编写为Function.prototype
或作为本机bind
函数的扩展。
- ES6构造函数返回基类的实例
- 使用Google Visualization动态调用构造函数
- javascript中对象构造函数中的var属性与this.properties
- 理解typescript中的构造函数接口
- AngularJS指令部分应用的函数don'不起作用
- 为什么构造函数不是构造函数
- 如果在构造函数中有“返回”,则在 JavaScript 中的新运算符中做了什么
- 拦截对构造函数的调用
- 使用闭包共享构造函数参数
- 文本表示法VS.构造函数,用于在JavaScript中创建对象
- 从js引擎的角度来看闭包和构造函数是如何工作的
- 应用构造函数特性没有结果
- $q服务 - 我应该在新的 AngularJS 应用程序中使用 CommonJS 风格还是构造函数风格
- 在 JavaScript 中绑定/应用构造函数
- RequireJS-将构造函数应用于模块
- 有可能用我的新上下文而不是原始的应用程序上下文来伪造WebView的构造函数吗
- 使用构造函数应用/调用
- 使用ES6构造函数渲染React组件的刷新页面会破坏应用程序
- 在使用Supertest测试express应用程序时,存根第三方库的构造函数
- Javascript调用并应用于构造函数