在JavaScript中绑定/应用构造函数 [英] binding/applying constructors in JavaScript

查看:190
本文介绍了在JavaScript中绑定/应用构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在寻找解决方案,用任意数量的参数调用Javascript构造函数,并发现一些好的SO帖子,这导致我相信这三个调用应该工作相同。但是,至少在rhino和node.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])$ ​​b $ b

第一个具有所需结果:

  print(new f())// => Sat Jan 01 2000 00:00:00 GMT-0500(EST)

t:

  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 和/或调用 c>

答案不正确。你可以使用绑定,调用和应用构造函数创建新的构造函数很好 - 你的测试中唯一的问题是你忘了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])$ ​​b
$ b 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)

$ c> instanceof Date。



调用的参数是应用参数的执行上下文。
Apply的参数是执行上下文和参数数组。
Bind的参数是执行上下文,后面是要绑定的参数。



因此,要应用的参数是例如应用绑定(日期),后跟一个数组,它是 bind的参数(因此第一个数组成员是绑定的上下文参数)。这就是为什么它是混乱的调用或应用绑定;注意,当使用bind和构造函数时,上下文参数总是被忽略,因为'new'显式地创建了一个新的上下文。



同时,在这些示例中应用和调用需要知道上下文参数是无关紧要的,在其中他们是应用/调用绑定是Date函数。我将日期切换到函数,尽可能帮助阐明实际提供上下文的位置。当我们在Date.bind上调用apply或call时,我们真的调用apply或调用绑定方法,而不绑定到Date对象。在这种情况下的绑定方法可以来自任何函数。它可以是Number.bind.call(Date,null,2000,0,1),结果将是完全一样的。



如果不明显为什么,以下示例之间的区别:

  context.method(); 

  var noLongerAMethod = context.method; 
noLongerAMethod();

在第二种情况下,该方法已经与原始上下文以前绑定),如果它在内部依赖this,它的行为会有所不同。当我们将任何给定的函数作为属性绑定时,而不是直接执行它,它只是另一个指向Function.prototype上的通用绑定方法的指针。



个人我不认为我需要调用或应用绑定,很难想象这将是一个很好的解决方案的情况,但绑定的构造函数创建新的构造函数是我发现非常有用的场合。在任何情况下,这是一个有趣的谜题。


I was looking for solutions for calling Javascript constructors with an arbitrary number of arguments, and found some good SO posts, which led me to believe that these three calls should work the same. However, at least in rhino and node.js, they do not:

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])

The first one has the desired result:

print(new f()) //=> Sat Jan 01 2000 00:00:00 GMT-0500 (EST)

But the other two don't:

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)

So something's gone haywire somewhere. Thoughts on what? Is it just a bad idea to mix things like apply, bind, and/or call with new?

解决方案

The accepted answer is incorrect. You can use bind, call and apply with constructors to create new constructors just fine -- the only problem in your test is that you've forgotten that bind.apply and bind.call are applying and calling bind, not the constructor itself, so you gave the wrong arguments.

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)

All three are instanceof Date.

Call's arguments are the execution context followed by the arguments to apply. Apply's arguments are the execution context and an array of arguments. Bind's arguments are the execution context followed by the arguments to bind.

So the arguments to apply, for example, are the context for which to apply bind (Date) followed by an array which is the arguments for bind (so the first array member is the bind's context argument). This is why it's confusing to call or apply bind; it feels strange to supply context arguments to both.

Note that, when using bind with constructors, the context argument is always ignored because 'new' explicitly creates a new context. I use null when the context argument is irrelevant to keep that clear, but it can be anything.

Meanwhile, apply and call in these examples do need to know that the context in which they are to apply/call bind is the Date function. I switched 'Date' to 'Function' where possible to help illuminate what is actually supplying context where. When we call apply or call on Date.bind, we are really calling apply or call on the bind method unattached to the Date object. The bind method in such a case could come from any function at all. It could be Number.bind.call(Date, null, 2000, 0, 1) and the result would be exactly the same.

If it's not obvious why, consider the difference between the following examples:

context.method();

and

var noLongerAMethod = context.method;
noLongerAMethod();

In the second case, the method has been divorced from its original context (...unless it was previously bound) and will behave differently if it was relying on 'this' internally. When we pull bind off any given function as a property, rather than executing it directly, it is simply another pointer to the generic bind method on Function.prototype.

Personally I don't think I've ever needed to call or apply bind, and it's hard to imagine a situation for which it would be a good solution, but binding constructors to create new constructors is something I've found very useful on occasion. In any case it's a fun puzzle.

这篇关于在JavaScript中绑定/应用构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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