VB, VBA, and VBScript pass arguments by reference by default. A subroutine definition can explicitly override the default by specifying that a parameter should be passed by value. This does raise two issues in the face of late-binding:

  1. How are arbitrary expressions passed by reference? The answer is that expressions which cannot be the target of assignments, for eg, x + 1, get evaluated into a temporary, and the temp variable then gets passed byref to the subroutine. So any modifications to the temp variable are not noticeable to the user. See the sample below.
  2. How does a call-site determine if the target subroutine expects the argument as byref or byval. The answer is that the callsite cannot know. It always passes the arguments as byref. The target function then takes care of reading the value out of the byref parameter and storing it in a temporary variable. Any updates made by the body of the target function only affect the temp variable.

Sub Foo(param)
    param = "Foo"
End Sub

Sub AssertValue(actualValue, expectedValue)
    If actualValue <> expectedValue Then
        MsgBox "Error! Expected " & expectedValue & " but got " & actualValue
    End If
End Sub

Dim x

x = 1
Foo x
AssertValue x, "Foo"

x = 1
Foo (x)
AssertValue x, 1

x = 1
Foo x+1
AssertValue x, 1