The scope is the characteristic that governs the accessibility of variables. The concept of scope is not easy to understand for many developers. In next sections this concept is explained and illustrated with several examples.

1 Global scope

When you start writing server side script in a document, you are already in the Global scope. There is only one Global scope throughout a server side script document. A variable is in the Global scope if it's defined outside of a function. A Global variable can be accesed in every local function.

Copy
<xsql-script name='test_global_var'>
    <body>
        <function name='local_test_global_var'>
            <body>

                <println>Value of variable [g_value] is: <global.get name='g_value' /></println>
            </body>
        </function>

        <global.set name='g_value' type='string'>GLOBAL SCOPE</global.set>
        <local_test_global_var />

    </body>
</xsql-script>
Value of variable [g_value] is: GLOBAL SCOPE
Copy
function fGlobalVar() {

        console.log(`fGlobalVar: Executing`);

        console.log(`fGlobalVar: Value of variable [gStrValue] is: ${gStrValue}`);

        console.log(`fGlobalVar: Exiting`);
    }

function testGlobalVar() {
    console.log(`testGlobalVar: Executing`);

    // console.log(`Value of variable [gStrValue] is: ${gStrValue}`); // ERROR!!!!!!!!!!!!!!!!!!!
    console.log(`testGlobalVar: Variable is not declared`); 
    gStrValue = 'GLOBAL SCOPE';
    console.log(`testGlobalVar: Variable is declared`); 
    console.log(`testGlobalVar: Value of variable [gStrValue] is: ${gStrValue}`);

    fGlobalVar();

    console.log(`testGlobalVar: Exiting`);
}

function testGlobalVarExtern() {
    console.log(`testGlobalVarExtern: Executing`); 
    //console.log(`Value of variable [gStrValue] is: ${gStrValue}`); // ERROR!!!!!!!!!!!!!!!!!!!!!!
    console.log(`testGlobalVarExtern: Variable is not declared`);   
    testGlobalVar();
    console.log(`testGlobalVarExtern: Value of variable [gStrValue] is: ${gStrValue}`);
    console.log(`testGlobalVarExtern: Exiting`); 
}
testGlobalVarExtern();
testGlobalVarExtern: Executing
testGlobalVarExtern: Variable is not declared
testGlobalVar: Executing
testGlobalVar: Variable is not declared
testGlobalVar: Variable is declared
testGlobalVar: Value of variable [gStrValue] is: GLOBAL SCOPE
fGlobalVar: Executing
fGlobalVar: Value of variable [gStrValue] is: GLOBAL SCOPE
fGlobalVar: Exiting
testGlobalVar: Exiting
testGlobalVarExtern: Value of variable [gStrValue] is: GLOBAL SCOPE
testGlobalVarExtern: Exiting

limit the use of global variables

A good practice limit the use of global variables. That is, inside the body of a function, never use variables defined outside the function.

2 Local scope

A variable declared within a function only can be accessed into the function where it is declared.

In next example a local variable is used outside the function where is declared, so causes an error.

Copy
<xsql-script name='test_local_var'>
    <body>
        <function name='local_var'>
            <body>

                <set name='m_var'>10</set>
            </body>
        </function>

        <local_var />
        <println><m_var /></println>
    </body>
</xsql-script>
undefined function or variable 'm_var'
Copy
function testLocalVar() {

    function __localVar() {
        var mIntLocVar = 10;
    }

    __localVar();

    console.log(mIntLocVar);
}
testLocalVar();
ReferenceError: "mIntLocVar" is not defined.

Precedences of local variables

In the function's body, the precedence of the local variable is more than the global variable with the same name. If the name of the function's local variable is same as the name of the global variable, then the local variable hides the global variable.

Copy
<xsql-script name='test_precedence'>
    <body>
        <function name='local_func'>
            <body>

                <set name='m_var'>5</set>

                <println><global.get name='m_var' /></println>
            </body>
        </function>

        <global.set name='m_var'>10</global.set>
        <local_func />
    </body>
</xsql-script>
10
Copy
function testPrecedence() {
    var mIntVar;

    function __localVar() {
        var mIntVar = 5;
        console.log("Inside _localVar : " + mIntVar);
    }

    mIntVar = 10;
    __localVar();
    console.log("Outside _localVar : " + mIntVar);
}
testPrecedence();
Inside _localVar : 5
Outside _localVar : 10

3 Block scope

A variable defined with var is globally scoped or locally scoped to the function in which it is defined. Control sentences as if, switch or loop sentences as for and while, that creates block scopes have no effect on var.

let and const, on the other hand, are scoped within the block which they are defined. In XSQL this scope does not exist. In next example javascript works differently than XSQL.

Copy
<xsql-script name='test_block_scope'>
    <body>
        <set name='m_var'>10</set>

        <if>
            <expr><true /></expr>
            <then>
                <set name='m_var'>5</set>
            </then>
        </if>

        <println>m_var = <m_var /></println>
    </body>
</xsql-script>
m_var = 5
Copy
var mIntVar = 10;
{
    let mIntVar = 5;
    console.log('mIntVar (inside block) = ' + mIntVar);
}
console.log('mIntVar (outside block) = ' + mIntVar);
mIntVar (inside block) = 5
mIntVar (outside block) = 10

In the exemple above, the declaration of mIntVar using let, is made within an if sentence. Outside the block, prevails the value assigned in declaration with global scope made just before the if statement.

4 Data types

Javascript variables are dynamically typed. If we declare variables and assign a value to it then it will convert that variable type. In script can function. XSQL works in a similar way.

Copy
<xsql-script name='test_type'>
    <body>
        <set name='m_var1'>10</set>
        <set name='m_var2'>10.45</set>
        <set name='m_var3'>LEON TROTSKY</set>
        <set name='m_var4'><date.today /></set>
        <set name='m_var5'><true /></set>
        
        <println>type [m_var1] <variable.typeof><m_var1 /></variable.typeof></println>
        <println>type [m_var2] <variable.typeof><m_var2 /></variable.typeof></println>
        <println>type [m_var3] <variable.typeof><m_var3 /></variable.typeof></println>
        <println>type [m_var4] <variable.typeof><m_var4 /></variable.typeof></println>
        <println>type [m_var5] <variable.typeof><m_var5 /></variable.typeof></println>
     </body>
</xsql-script>
type [m_var1] java.lang.Integer
type [m_var2] java.math.BigDecimal
type [m_var3] java.lang.String
type [m_var4] java.sql.Date
type [m_var5] java.lang.Boolean
Copy
var mIntVar1 = 10;
var mBcVar2 = 10.45;
var mStrVar3 = 'LEON TROTSKY';
var mJsDateVar4 = new Date();
var mBoolVar5 = true;

console.log(`type [mIntVar1] ${typeof mIntVar1}`);
console.log(`type [mBcVar2] ${typeof mBcVar2}`);
console.log(`type [mStrVar3] ${typeof mStrVar3}`);
console.log(`type [mJsDateVar4] ${typeof mJsDateVar4}`);
console.log(`type [mBoolVar5] ${typeof mBoolVar5}`);
type [mIntVar1] number
type [mBcVar2] number
type [mStrVar3] string
type [mJsDateVar4] object
type [mBoolVar5] boolean

XSQL data types vs javascript data types

The main difference that can be observed in last example is the data types obtained. The types used in XSQL are derived from java classes. In any case, as you will see in this section, there are objects in server side javascript that also derive from java classes.

5 Several variables in a line

In javascript we can assign several variables in a single statement, while in XSQL no.

Copy
<xsql-script name='test_statement_multidefs'>
    <body>
        <set name='m_var1'>10</set>
        <set name='m_var2'>20</set>                                                     
        <set name='m_var3'>30</set>
        
        <println> m_var1 1 [<m_var1 />] m_var2 [<m_var2 />] m_var3 [<m_var3 />] </println>
     </body>
</xsql-script>
m_var1 1 [10] m_var2 [20] m_var3 [30]
Copy
var mIntVar1 = 10, mIntVar2, mIntVar3 = 30;
mIntVar2 = 20;

console.log('mIntVar1 [' + mIntVar1 + '] mIntVar2 [' + mIntVar2 + '] mIntVar3 [' + mIntVar3 + ']');
mIntVar1 [10] mIntVar2 [20] mIntVar3 [30]

6 Declaring variables without values assigned

In XSQL there is no way to declare a variable without assigning a value to it. On the other hand, in server side script you can define a variable with let, var and const, assigning it a value later. The value of the variable after assignment is undefined.

Copy
var mIntVar;
console.log("BEFORE ASSIGN VALUE: " + mIntVar);

mIntVar = 10;
                
console.log("AFTER ASSIGN VALUE: " + mIntVar);
BEFORE ASSIGN VALUE: undefined
AFTER ASSIGN VALUE: 10

7 Assigning decimal values

Javascript decimal numbers are floating-point numbers, and so are represented as binary fractions. Unfortunately most decimal fractions cannot be represented exactly as binary fractions.

Copy
<xsql-script name='test_bigDecimal'>
    <body>
        <set name='m_var1'><add><number>0.1</number><number>0.2</number></add></set>
        
        <println> m_var1: [<m_var1 />]</println>
     </body>
</xsql-script>
m_var1: [0.3]
Copy
var mDecVar1 = 0.1 + 0.2

console.log("m_var1: [" + mDecVar1 + "]");
m_var1: [0.30000000000000004]

This problem does not exists in XSQL, because use java.math.BigDecimal. But in Server side script there is also the possibility of working with big decimal using Ax.math.bc. In next example we resolve the above problem.

Copy
var mBcVar1 = 0.1;
var mBcVar2 = 0.2;

console.log("m_var1: [" + Ax.math.bc.add(mBcVar1, mBcVar2) + "]");
m_var1: [0.3]

8 Date variables

Sometimes if we are migrating from XSQL, we need to perform calculations with date types or use date types in database operations. In this cases, primitive javascript date type is not the best solution. In server side script we have a java.util.Date object wrapper that simplify these operations.

Copy
<xsql-script name='test_date'>
    <body>
        <set name='m_var_date'><date.mdy><number>1</number><number>1</number><number>2030</number></date.mdy></set>
        <set name='m_var_date'><add><m_var_date /><date.units type='m'>1</date.units></add></set>

        <println>m_var_date: <m_var_date /></println>
     </body>
</xsql-script>
m_var_date: 01-02-2030
Copy
var mDateVar = new Ax.util.Date(2030, 1, 1);
var mDateVar = mDateVar.addMonth(1);

console.log("m_var1: [" + mDateVar + "]");
m_var1: [Fri Feb 01 00:00:00 CET 2030]