0

我试图为遗留的Classic ASP应用程序带来一些理智,作为其中的一部分,我正在尝试为我创建的一些JScript类编写一个Fluent API 。

例如myClass().doSomething().doSomethingElse()

这里概述了这个概念(在 VBScript 中)

这是我的示例JScript类:

var myClass = function () {
    this.value = '';
}

myClass.prototype = function () {

    var doSomething = function (a) {
        this.value += a;
        return this;
    },

    doSomethingElse = function (a, b) {
        this.value += (a + b);
        return this;
    },

    print = function () {
        Response.Write('Result is: ' + this.value + "<br/>");
    }

    return {
        doSomething: doSomething,
        doSomethingElse: doSomethingElse,
        print: print
    };

}();

/// Wrapper for VBScript consumption
function MyClass() {
    return new myClass();
}

在现有的 VBScript 代码中,我尝试将这些方法链接在一起:

dim o : set o = MyClass()
'' This works
o.doSomething("a")

'' This doesn't work
o.doSomething("b").doSomethingElse("c", "d")

'' This for some reason works
o.doSomething("e").doSomethingElse("f", "g").print()

当函数有多个参数时,我得到“ Cannot use parentheses when calling a Sub” VBScript 错误。奇怪的是,当采用另一种方法时,它似乎有效。

我知道在调用 sub 时应该省略括号。然而:

1、有返回值为什么会被识别为Sub?

2. 有什么办法可以实现我的 Fluent API?

4

3 回答 3

5

规则是:将“命名代码段”作为 sub调用时没有参数 list () 。讨厌的陷阱是:对于单参数 npcs,()可能看起来像参数列表(),但(解释为)pass-me-by-value()。

set o = MyClass()将 myClass() 称为函数;从任务中可以清楚地看出这一点。

o.doSomething("a")将 .doSomething 作为子调用, () 被视为 pass-me-per-value (); doSomething "a"将是正确的电话。

您作品的第一部分o.doSomething("b").doSomethingElse("c", "d"),因为o.doSomething("b").是/使用函数调用来获取.doSomethingElse()要调用的对象;第二部分.doSomethingElse("c", "d")不能工作,因为它不是子调用(没有使用/分配返回值),并且() 不能被视为 pass-me-by-value ()。o.doSomething("b").doSomethingElse "c", "d"会是正确的。

第一部分o.doSomething("e").doSomethingElse("f", "g").print()(直到.print)是一个函数调用(获取将要.print的对象),所以()是参数列表();.print 之后的 () 是错误的,但编译器/解释器让它们溜走了。

总结一下:当你不想要一些东西时,不要使用 () 。

WRT评论:

反过来说:当你想要一些东西时使用 () !

set o1 = MyClass()<- 返回值应该进入 o1

set o2 = o.S(1, 2).S(3, 4).S(5, 6)<- 下一次调用需要/使用前两个返回值;最后一个返回值进入 o2。

o.S(1, 2).S(3, 4).S 5, 6<- 最后一个返回值被丢弃 - 没有子调用

() 规则是关于你做什么(使用或不使用返回值),而不是关于 npc什么。

于 2013-01-09T16:44:01.270 回答
3

您可以将callvbscript 放在每一行的开头。这将接受在每个方法调用上放置括号,例如

' This works
call o.doSomething("b").doSomethingElse("c", "d")

' This works too
call o.doSomething("e").doSomethingElse("f", "g").print()

或者当它抱怨时不要把括号放在vbscript中......

请参阅VBScript 和 JavaScript 之间的差异

于 2013-01-09T16:26:28.773 回答
2

顺便说一句,您可以在 VBScript 中编写流畅的 API。我建立了一个库来促进 HTML 的内联创建以避免“标签汤”垃圾,我现在正在应用程序中使用它(这就是我发现这个问题的方式)。

这是一个使用几个助手包裹 960gs 网格的示例:

with html
  .open
    with head
      .open
        stylesheet_link "assets/stylesheets/960gs/reset.css"
        stylesheet_link "assets/stylesheets/960gs/960.css"
        stylesheet_link "assets/stylesheets/960gs/text.css"
        stylesheet_link "assets/stylesheets/app.css"
      .close
    end with
    with body
      .open
        with grid_container(12)
          .open
            call main
          .close
        end with
      .close
    end with
  .close
end with

然后 main 可能与此类似:

with grid_row
  with grid_column(4)
    .id "nav-left"
    .open
      with ul
        .open
          li.open.contains( link_to("Google", "http://google.com") ).close
          li.open.contains( link_to_if(a > b, "Microsoft", "http://microsoft.com") ).close
          li.open.contains( link_to_unless(a > b, "Apple", "http://apple.com") ).close
        .close
      end with
    .close
  end with
  with grid_column("8 push_2")
    .id "main-content"
    .open
      h1.open.contains("Title Here").close
      do until recordset.eof
        p.class("record").open.contains(recordset("column_name")).close
        recordset.movenext
      loop
    .close
  end with
end with

该库的编写方式基本上可以零努力地生成 XML,基本上是任何具有“具有属性的嵌套元素”结构的标记语言。

经典 ASP 看起来是这样的,因为使用 (d) 它的人和制作教程的人只是把它扔在那里,并没有完全理解语言和良好实践。所以我们被困在维护蜿蜒的代码呕吐物。但如果你做得对,它就会开始看起来像红宝石。哎呀,几年前我什至使用动态 vbscript 类实现了一些 ruby​​ 迭代的东西,只是为了看看我是否可以做到并且它有效,但我很久以前就丢失了那个代码。重点是即使 vbscript 是有限的,它仍然比人们认为它具有更多的能力,他们只是通常不会做事情,因为可以做。

于 2013-02-13T17:29:36.793 回答