7

目前我必须处理用 VB 编写的遗留系统。我不擅长 VB 和 ASP,所以我决定这个系统的新代码将用 JScript 编写。

但是,两种语言之间的互操作性存在一些问题:即,当我尝试调用<script language="vbscript">标记中声明的某个函数时,它会失败并出现“预期对象”错误(如果页面语言是 VBScript),反之亦然。

即,以下代码:

inc.asp

<script language="vbscript" runat="server">
Sub VBTestFunction(Message)
    Response.Write "VBTestFunction: " & Message
End Sub
</script>
<script language="javascript" runat="server">
function JSTestFunction(Message) {
    Response.Write("JSTestFunction: " + Message);
}
</script>

测试js.asp

<%@ Language="JavaScript" %>
<!-- #include file="inc.asp"-->
<script language="javascript" runat="server">
    VBTestFunction("from javascript");
    JSTestFunction("from javascript");
</script>
<script language="vbscript" runat="server">
    Call VBTestFunction("from vbscript")
    Call JSTestFunction("from vbscript")
</script>

失败并出现以下错误:

VBTestFunction: from vbscript
Microsoft VBScript runtime error '800a000d'
Type mismatch: 'JSTestFunction'
/test.asp, line 9

(如果我将评论特定行,其他三个语句将正常工作);将页面语言设置为 VBScript

<%@ Language="VBScript" %>
<!-- #include file="inc.asp"-->
<script language="javascript" runat="server">
    VBTestFunction("from javascript");
    JSTestFunction("from javascript");
</script>
<script language="vbscript" runat="server">
    Call VBTestFunction("from vbscript")
    Call JSTestFunction("from vbscript")
</script>

失败并出现以下错误:

Microsoft JScript runtime error '800a138f'
Object expected
/test.asp, line 4

(再次,如果我将注释掉特定行,其他三个语句将正常工作)。

有一篇关于在同一个应用程序中混合 VB 和 JS 的MSDN 文章,但从文章看来,示例代码应该可以工作,正如TestFunction在另一个文件中声明的那样,毕竟是一个函数。

有什么方法可以让这一切工作,并同时调用VBTestFunctionVBJSTestFunction和 JS 代码?我想应该有一个,否则混合JS和VB就没有意义了。

4

3 回答 3

6

我一直在关注这个问题,萨尔曼已经回答了很多,但有些事情可以澄清。首先,被引用的文章存在关键问题。它说执行顺序是这样的:-

1.非默认语言的元素中的脚本 2.内
联脚本
3.默认语言的元素中的脚本

它是错误的,或者至少是过时的(毕竟它确实引用了 IIS4)。“内联脚本”(即默认语言的脚本)的处理方式与相同语言的脚本元素没有任何不同。

以下是如何通过正在发生的事情进行推理。

  • 在任何解析开始之前,所有的包含点都被解析并被包含文件中的内容替换,以创建一个单一的词法“文件”。这是在任何解析发生之前创建的。

  • 从这个“文件”中收集每种语言的脚本代码。您可以想象在找到每个块时附加多个文件(每种语言一个)。请注意,这就是为什么<% %><script runat="server"默认语言实际上无法区分的原因。

  • 任何静态内容(即runat="server"脚本标记或之外的内容<% %>)都被视为默认语言代码的一部分。创建了一种将静态内容字节逐字发送到响应的特殊形式Response.Write,并将其附加到在原始文件中找到的默认语言代码中。

  • 现在我们有一个或多个脚本准备好由它们各自的脚本引擎处理。非默认语言脚本首先被解析执行。为函数或变量创建的任何全局标识符都将添加到脚本环境中。但是,由于此时根本没有处理默认语言脚本,因此它可能随后添加到全局脚本环境中的任何内容都还没有可用。

  • 到解析和执行默认语言脚本时,由先前语言脚本创建的所有全局标识符都将被添加到脚本环境中,因此可以从内联代码中使用。

您应该仔细注意,默认语言函数可以由非默认语言的函数中的代码调用,条件是调用非默认函数可以追溯到默认语言的内联执行。

例如,如果默认语言是JScript您可以让VBScript函数 (fnA) 调用在JScript(fnB) 中声明的函数,只要调用fnA是作为JScript内联执行的一部分进行的。IOW JScript 可以调用 VBScript,VBScript 又可以调用 VBScript 等等,限制因素是在这种情况下这个链的顶部必须是 JScript 的引擎。

在您的示例代码中,您的 VBScript 全局(内联)级别的代码试图调用以默认 JScript 语言声明的函数。如果您按照上面的项目符号进行操作,您将看到在执行时被调用的函数不存在。

于 2012-04-10T19:32:10.573 回答
2

我鼓励您不要混合使用脚本语言。在您提到的文章中,有一个标题为“服务器脚本执行顺序”的标题,其中写道:

...但是,您将受到 IIS ASP 处理器的执行顺序的支配。例如,如果您创建服务器脚本并在 IIS 4.0 中运行它,您会发现以下执行顺序:

  1. 非默认语言的 <SCRIPT> 元素中的脚本
  2. 内联脚本
  3. 默认语言的 <SCRIPT> 元素中的脚本

请记住,以下是 testjs.asp 脚本的执行方式,注释指示执行顺序:

<%@ Language="JavaScript" %>
<script language="vbscript" runat="server">
    '' #1
    Sub VBTestFunction(Message)
        Response.Write "VBTestFunction: " & Message
    End Sub
</script>
<script language="javascript" runat="server">
    // #3
    function JSTestFunction(Message) {
        Response.Write("JSTestFunction: " + Message);
    }
</script>
<script language="javascript" runat="server">
    // #4
    VBTestFunction("from javascript");
    JSTestFunction("from javascript");
</script>
<script language="vbscript" runat="server">
    '' #2
    Call VBTestFunction("from vbscript")
    Call JSTestFunction("from vbscript")
</script>

注意导致错误的行:

Call JSTestFunction("from vbscript")

它的执行顺序是#2;此时该函数JSTestFunction尚未定义(它在执行顺序的后面定义)。

现在为 testvbs.asp 文件:

<%@ Language="VBScript" %>
<script language="vbscript" runat="server">
    '' 3
    Sub VBTestFunction(Message)
        Response.Write "VBTestFunction: " & Message
    End Sub
</script>
<script language="javascript" runat="server">
    // 1 
    function JSTestFunction(Message) {
        Response.Write("JSTestFunction: " + Message);
    }
</script>
<script language="javascript" runat="server">
    // 2
    VBTestFunction("from javascript");
    JSTestFunction("from javascript");
</script>
<script language="vbscript" runat="server">
    '' 4
    Call VBTestFunction("from vbscript")
    Call JSTestFunction("from vbscript")
</script>

导致错误的行:

VBTestFunction("from javascript");

同样,VBTestFunction在定义之前调用。解决方案是尽量不要混合脚本语言。如果绝对有必要,请修改脚本的顺序。

编辑——示例

如果您已设置@ Language="JavaScript",则此代码应按预期工作:

<!-- inc.asp-->
<script language="vbscript" runat="server">
    Sub VBTestFunction(Message)
        Response.Write "VBTestFunction: " & Message
    End Sub
</script>
<%
    function JSTestFunction(Message) {
        Response.Write("JSTestFunction: " + Message);
    }
%>

<!-- testjs.asp -->
<%@ Language="JavaScript" %>
<!-- #include file="inc.asp"-->
<%
    // at this point, both functions are available
    VBTestFunction("from inline JavaScript");
    JSTestFunction("from inline JavaScript");
%>

如果要使用,@ Language="VBScript"则必须重新排列所有代码:

<!-- inc.asp-->
<script language="javascript" runat="server">
    function JSTestFunction(Message) {
        Response.Write("JSTestFunction: " + Message);
    }
</script>
<%
    Sub VBTestFunction(Message)
        Response.Write "VBTestFunction: " & Message
    End Sub
%>

<!-- testvbs.asp -->
<%@ Language="VBScript" %>
<!-- #include file="inc.asp"-->
<%
    ' at this point, both functions are available
    VBTestFunction("from inline VBScript")
    JSTestFunction("from inline VBScript")
%>
于 2012-04-10T09:13:12.047 回答
0

我不知道所有规则,但这对我有用:

测试.asp:

<%@ language="JavaScript" %>

<script language="VBScript" runat="server" src="mix2.vbs"></script>

<script language="JavaScript" runat="server">
    TestFunction("from javascript");
</script>

mix2.vbs:

Sub TestFunction (message)
    Response.Write message
End Sub

注意:

  • <script>vbs 文件中没有包含的标签。
  • <%@ language="..." %>顶部的标签应指明“主要”语言。然后<script>,使用辅助语言(在您的情况下为 VBScript)的块将被解释并可用于主要语言的任何代码。

也许相关:如何在 ASP-Classic 或 WSH 环境中使用 VBScript 中的 Javascript OO 类?

于 2012-04-10T06:34:35.347 回答