Нello!如果可以调用类的实例,则有时可以特别干净地编写API。当类的操作比其他任何操作都常见时,这似乎特别有用。
例如,考虑一个用于定义树的库,其中树中的每个Node
都有一个值和一个子节点的索引列表:
let Node = function(value, children) { /* ... */ };
Node.prototype = { /* ... */ };
let root = new Node('root', [
new Node('child1', [
new Node('grandchild11', []),
new Node('grandchild12', [])
]),
new Node('child2', [
new Node('grandchild21', []),
new Node('grandchild22', [])
])
]);
我想说Node
的操作比其他任何操作都更为普遍:让孩子处于特定的索引位置:
root.getChild(1); // Returns the "child2" node (0-based indexing)
我要说的是,这种操作是如此普遍,通过以下方式获得相同的结果将非常容易阅读和干净:
root(1);
但是要启用这样的语法,root
必须是可调用对象(因此Node
构造函数将需要返回可调用对象)。链接时,这样的功能真的很棒!:
root(0)(1); // Returns `grandchild12`
可以想象,使用这种语法可以传递其他类型,例如传递函数可以返回与搜索匹配的节点:
root(node => node.value === 'child1')(node => node.value === 'grandchild11');
是否有一些聪明的(元编程)技术可以使javascript的new
关键字返回可调用对象,并简化诸如此类的语法?
请注意,对于更复杂的API,多态性成为一项重要功能!如果可能的话,我想保留对象的原型链。
注意:
Jsperf比较可调用实例(root(0)
)和实例方法(root.getChild(0)
)似乎向我展示(Chrome 72.0.3626)可调用实例是a tiny bit slower。
答案 0 :(得分:2)
当然,通过new
进行的调用可以返回任何类型的对象,包括函数。的确,使用new
调用函数会自动用新创建的对象填充this
,但您不必让this
作为构造函数的返回值:只需{{1 }}任何其他对象。
您真正想要的是拥有return
是一种功能。只需让您的Node
构造函数返回具有适当属性和原型链的函数对象即可。您需要确保
Node
原型对象Node
原型对象继承自Node
,以便您的Function.prototype
实例获得Node
和call
之类的Function方法例如:
bind