2

DOMThreeJS和现在的canvas都编写了提供方法链接的库(可能最熟悉的 jQuery )。链接也被用于核心 C 库中。

这些流畅的界面避免了对感兴趣对象的不必要重复。比较:

var cx = cq(640, 480);
cx.drawImage(image, 0, 0);
cx.fillStyle("#ff0000");
cx.fillRect(64, 64, 32, 32);
cx.blur();
cx.appendTo("body");

到:

cq(640, 480)
  .drawImage(image, 0, 0)
  .fillStyle("#ff0000")
  .fillRect(64, 64, 32, 32)
  .blur()
  .appendTo("body");

可以说,以前的“传统”风格过于冗长,违反了DRY

为了避免变量的重复cx,一些语言允许我们使用with语句来表达一组调用:

with ( cq(640, 480) ) {
    drawImage(image, 0, 0);
    fillStyle("#ff0000");
    fillRect(64, 64, 32, 32);
    blur();
    appendTo("body");
}

虽然 JavaScript 的with语句在存在拼写错误的情况下很危险,但Scala 的限制性更强的with语句使用起来很安全,而且 Haxe 还通过其using关键字将函数导入到本地范围。不幸的是,Java 和 C 没有提供这样的捷径,迫使我们在传统代码或链接之间做出选择。

语言作者应该考虑使用类似安全with的语句作为方法链接的替代方案,还是有充分的理由避免使用它?如果这样的功能是可取的,它应该采取什么形式?


我对方法链接的一个担忧是,关于链中后续调用的主题的模糊性可能会阻止在编译代码时先前可用的优化,其中重复使用cx是明确的。例如,如果对cx's 方法的调用不重叠,它们可以被并行化,但编译器在链接示例中可能更难确定这一点。

正如 rambo 在下面指出的那样,另一个缺点是为链接设计的方法无法返回任何其他值,这似乎相当浪费。

4

2 回答 2

2

它被称为方法链。它经常出现在Fluent Interface的讨论中。

也许最大的缺点是你不能返回一个值,因为你必须返回隐含的对象才能允许链接。如果没有返回值,并非所有方法都有意义,然后您最终会得到一个具有一些可链接方法的接口,而有些则没有。

我不认为它表示缺少语言功能,因为没有它就不会严重丢失功能。但是像这样的语言支持可能很有趣。

于 2013-01-05T02:23:25.427 回答
1

这不是缺少的语言功能,而是一种语言功能。如果它丢失了,那么它就不可能在 Javascript 中完成。

这不是语法。相反,它是一种设计模式。它被称为链接。事实上,有一些库可以单独实现链接。例如,DED|Chain 是一个为 YUI2 实现链接的库,在编写时并没有考虑到链接。

无论您如何称呼它(您建议使用名称“on”但它会遇到“with”所具有的所有问题),像这样的专门语法with(确实像您提到的那样在 js 中实现)都是有问题的。

问题是,在代码块中,如果方法或变量引用对象的方法,或者如果有错字并且意外引用全局变量或不是对象的一部分但在范围内的变量。

当然,您可以说程序员的工作是确保他们不使用可能引起混淆的变量和方法名称。在这种情况下,您可以使用with.

于 2013-01-05T02:12:42.783 回答