-2

I'm working on an old application that often declares variables that seem to be global, using identifiers likely to be used elsewhere.

When writing a function, some parameters happen to have the same name as those global variables, and it is hardly avoidable, because one doesn't know if that identifier is already in use by one of these global variables, or it might be, but within a script that ends up not being called.

SomeRandomPage.asp :

foo = "bar" ' Not sure if it's declared with Dim or not

MyFunction.asp :

Function MyFunction(foo) ' Same name as global variable "foo"
    foo = foo & "123"
    MyFunction = foo
End Function

If the function affects a value to that parameter, the global variable also appears to be modified, like VB Script didn't care about variable scopes at all.

Dim bang : bang = "hello"

Response.Write foo ' "foo"

bang = MyFunction(bang)

Response.Write foo ' "hello123"

The solution I was suggested is to declare local variables in my function using Dim, copying my parameters into those local variables, and using those local variables instead of the parameter.

Function MyFunction(foo)
    Dim localFoo : localFoo = foo
    localFoo = localFoo & "123"
    MyFunction = localFoo
End Function

As poor as VB Script can be, I can't imagine that this dirty method would be the only solution to avoid this global variable overwriting behaviour.

So my question is : how can I prevent global variables from being overwritten by assigning values to function parameters that happen to have the same name ?

halfer
  • 19,824
  • 17
  • 99
  • 186
Virus721
  • 8,061
  • 12
  • 67
  • 123
  • 1
    And that boys and girls is why we don't use global variables ;) – Geert Bellekens Apr 26 '23 at 16:30
  • I can't replicate this issue with a simple VBS or HTA file. Is the result the same if the code is all in one ASP file? – LesFerch Apr 26 '23 at 17:07
  • This does not need a massive discussion pass the `foo` argument `ByVal` instead of `ByRef` (which is the default) as the [Official Documentation](https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/scripting-articles/ee478101(v=vs.84)) states. – user692942 Apr 26 '23 at 17:23
  • 1
    Does this answer your question? [What does ByRef mean in vbscript when passing to a procedure?](https://stackoverflow.com/questions/9470846/what-does-byref-mean-in-vbscript-when-passing-to-a-procedure) – user692942 Apr 26 '23 at 17:25
  • @user692942 Of course, `byval` solves it when you actually pass `foo`, but the OP's example passes `bang`. – LesFerch Apr 26 '23 at 17:28
  • OP, are you sure that example is correct? The observed behavior is expected when you pass the global `foo` to the function byref (the default). If your example had been `bang = MyFunction(foo)`, then the global `foo` will be changed. As noted, to resolve that, you would just have to revise the function to `Function MyFunction(byval foo)`. – LesFerch Apr 26 '23 at 17:56
  • @LesFerch as you’ve realises it doesn’t matter what is passed into the function if the function definition for that argument is prefixed `ByVal`. In other words adjust the function definition to `Function MyFunction(ByVal foo)`, that way you can pass whatever scoped variable into it you want and it won’t be affected as it’s not being passed by reference. – user692942 Apr 26 '23 at 18:34
  • @user692942 I think you missed my point. The global `foo` should not change, given the OP's example. `Function MyFunction(foo)` creates a *local* `foo` variable (at least it does in my tests). If the OP had passed `foo` *into* the function, then we would expect the global `foo` to change. But the OP claims to have passed `bang`. In that case, the global `foo` should not change. Adding `byval` would only make a difference if the global `foo` *is* being passed into the function. – LesFerch Apr 26 '23 at 19:53
  • I just noticed that the first `Response.Write`, in the example above, shows "foo", where we expect to see "bar". Seems to be a typo. – LesFerch Apr 26 '23 at 20:31
  • 1
    The OPs intent is not clear but if you want to stop a global variable being overwritten in a function you either declare the argument `ByVal` (if the global variable is being passed into the function) or make sure any variable name conflict in the function is removed by declaring local variables with `Dim`. – user692942 Apr 27 '23 at 07:07

2 Answers2

1

Here's the OP's code with the only change being MsgBox instead of Response.Write:

foo = "bar"

Function MyFunction(foo)
  foo = foo & "123"
  MyFunction = foo
End Function

Dim bang : bang = "hello"
MsgBox foo
bang = MyFunction(bang)
MsgBox foo

The OP claims that foo will be set to "hello123", but running this code as a VBS file, foo remains set to "bar".

Here are two possible explanations:

  1. In the actual production code, foo is being passed into the function (instead of bang).

  2. In the actual production code, the function argument is something different than foo, but foo is being changed within the function.

LesFerch
  • 1,540
  • 2
  • 5
  • 21
0

You could create a clsGlobals class for your global variables:

Class clsGlobals
    Public foo
End Class

You'd create a single instance of this class:

Dim Globals
Set Globals = New clsGlobals

And replace your global foo variable with Globals.foo

This would resolve the naming conflicts and also make it obvious the variable you are using is a global variable. This does not prevent global variables from being overwritten but I think it's a good solution.

Étienne Laneville
  • 4,697
  • 5
  • 13
  • 29
  • Thanks for your answer, but unfortunately I can't afford to rewrite so many things in the application (there's really many of them, in many files). I was thinking more about a solution on the funtion's side. – Virus721 Apr 26 '23 at 16:52
  • Then I think your only choice is to use a different name for your function parameters, like `p_foo` for example. – Étienne Laneville Apr 26 '23 at 16:55