我正在尝试为传统的经典ASP 应用程序带来一些理智,作为其中的一部分,我正在尝试为某些 Fluent API >我创建的JScript 类。
e.g。 myClass().doSomething().doSomethingElse()
概述概述here(在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?
答案 0 :(得分:5)
规则是:在将“命名代码段”作为子调用时,没有参数列表()。令人讨厌的陷阱是:对于单个参数npcs,()可能看起来像param list(),但是(解释为)pass-me-by-value()。
您的set o = MyClass()
将我的MyClass()调用为函数;从作业中可以清楚地看出。
你的o.doSomething("a")
来电.doSomething as sub,()被视为pass-me-per-value(); doSomething "a"
将是正确的电话。
o.doSomething("b").doSomethingElse("c", "d")
的第一部分有效,因为o.doSomething("b").
是/使用函数调用来获取要调用.doSomethingElse()
的对象;第二部分.doSomethingElse("c", "d")
不起作用,因为它不是一个子调用(没有使用/分配的返回值)和()不能被视为传递给我by-value()。 o.doSomething("b").doSomethingElse "c", "d"
是正确的。
第一部分o.doSomething("e").doSomethingElse("f", "g").print()
(直到.print)是一个函数调用(获取将.print的对象),所以()是param list(); .print之后的()是错误的,但编译器/解释器让它们溜走了。
总结一下:当你不想要某些东西时,不要使用()。
WRT评论:
换句话说:使用()当你想要回来的时候!
set o1 = MyClass()
&lt; - 返回值应该进入o1
set o2 = o.S(1, 2).S(3, 4).S(5, 6)
&lt; - 下一个呼叫需要/使用前两个返回值;最后一个返回值进入o2。
o.S(1, 2).S(3, 4).S 5, 6
&lt; - 丢弃最后一个返回值 - 没有子调用
()规则是关于你做什么(是否使用返回值),而不是关于npc 是什么。
答案 1 :(得分:3)
您可以将call
放在每行vbscript的开头。这将接受在每个方法调用上放置的括号,例如
' This works
call o.doSomething("b").doSomethingElse("c", "d")
' This works too
call o.doSomething("e").doSomethingElse("f", "g").print()
或者只是在抱怨时不要将parantheses放在vbscript中......
答案 2 :(得分: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
编写lib的方式可以生成基本上没有努力的XML,基本上任何标记语言都具有“具有属性的嵌套元素”结构。
经典ASP看起来就像它所做的那样,因为使用(d)它的人和制作教程的人只是把它扔出去并且没有完全理解语言和良好实践。所以我们坚持维持蜿蜒的代码呕吐。但如果你做得对,它可能会开始看起来像红宝石。几年前我甚至使用动态vbscript类实现了一些ruby迭代的东西只是为了看看我是否可以做到并且它有效,但是很久以前我丢失了这段代码。要指出的是,尽管vbscript是有限的,但它仍然具有比人们认可的更多的能力,他们通常不会做得那么好。