Forum Discussion

sbkeenan's avatar
sbkeenan
Frequent Contributor
11 years ago

JScript vs VBScript

Hi all



I've been using TestComplete for a few years now and have been writing scripted tests in VBScript and have to say that I've never encountered any problems with doing so (at least no issues with VBScript!!)



I'm now trying my hand at JScript and, thus far, have managed to replicate one of my class files that I'd written in VBScript.  I've even got my head round the idea of prototyping, in that I've created a function (class for want of a better description) and have added several methods to its prototype.  I can cerate an instance of it in anouther project and call any of the methods - so far, so good.  I am, however, finding it a little frustrating in the way I have to handle any application properties that I need to work with.  For example, in VBScript, if I need to work with the contents of a text field and compare it to another string value, I simply use the wText or Text properties, something like this:





if (aTextBox.wText = myCompareStr) then ....end if





In JScript, the only way I can get this to work is like this:





var textBoxText = new String(aTextBox.text);

textBoxText = textBoxText.toString();

if (textBoxText == myCompareStr) {.......}





I find that I also have to do similar conversions when working with integer values using the Number function.



Am I missing something here or is this just how JScript must work?  It seems like a lot of extra work.  Since JScript doesn't have typed variables (like VBScript), why can't it just work directly with the properties?  Is it because everything in JScript is an object and in the case of strings and integers (and presumably other primitive types), we need to do an explicit conversion?



Any assistance or explanations welcome!!



Regards

Stephen.



  • Hi Stephen,



    This is interesting... I never ran into your issue because all our application (VS C++) elements that respond to wText return a String.



    With the following test code:



    function someString() {

      this.type = "someString";

    }


    someString.prototype.getString = function (){

        return new Object("aString for class " + this.type);

      }



    function TestStringVar()

    {

      var aStringObject = new someString();

      var anObject = new Object("someOtherString");

     

      Log.Message(aStringObject.getString()); 

      Log.Message(aStringObject.getString().toLowerCase()); 

      Log.Message(aStringObject.toString());

     

      // This raises the exception that triggered this thread

      //Log.Message(aStringObject.toLowerCase());

      

      Log.Message(anObject.toLowerCase()); 

      Log.Message(anObject.toString());

      Log.Message(anObject);

     

    }



    And with your code, I can reasonnably assume that if textBox.wText.toLowerCase() doesn't work, textBox.wText.toString().toLowerCase() will.



    Sincerely


  • simon_glet's avatar
    simon_glet
    Regular Contributor
    Hi Stephen,



    All our scripts are in JScript and we never had to convert properties for comparison like you did. The only thing I can think of is that the property .text does not return a String.



    Keep in mind that in JScript objects can have different types (attached screenshot)



    What does (aTextBox.wText == myCompareStr) return in JScript ?



    Sincerely
  • simon_glet's avatar
    simon_glet
    Regular Contributor
    Hi Stephen,



    This is interesting... I never ran into your issue because all our application (VS C++) elements that respond to wText return a String.



    With the following test code:



    function someString() {

      this.type = "someString";

    }


    someString.prototype.getString = function (){

        return new Object("aString for class " + this.type);

      }



    function TestStringVar()

    {

      var aStringObject = new someString();

      var anObject = new Object("someOtherString");

     

      Log.Message(aStringObject.getString()); 

      Log.Message(aStringObject.getString().toLowerCase()); 

      Log.Message(aStringObject.toString());

     

      // This raises the exception that triggered this thread

      //Log.Message(aStringObject.toLowerCase());

      

      Log.Message(anObject.toLowerCase()); 

      Log.Message(anObject.toString());

      Log.Message(anObject);

     

    }



    And with your code, I can reasonnably assume that if textBox.wText.toLowerCase() doesn't work, textBox.wText.toString().toLowerCase() will.



    Sincerely


  • Couple of points to make here:



    I've been writing Javascript for 15 years or so and I can probably count the number of times I've genuinely needed to use new String(), new Array(), new Object(), etc on the fingers of one hand. 



    new String() isn't used to initialise a string value, it's to create an object which inherits from the String prototype, to which you can attach new properties and methods.





    Another thing is that the .toString() method of your text object may be a method of that object in its original development language, not the similarly name javascript method.



    For instance, in a Java SWT application there may be fields that contain Java strings, which appear to have text values but javascript can only interpret the object's OleValue property as a string. The Object Browser is your friend here.





    Lastly, if you like the terseness of LCase, simply declare a function to do the equivalent, rather than writing out the conversion long-hand every time.











  • sbkeenan's avatar
    sbkeenan
    Frequent Contributor
    Hi Simon



    I think I've got it now!!



    Looking back at my example, I can see that it was a poor one because the wText property does actually return a String value and works.  I just used it as an example, on the assumption (silly me!) that it would behave in the same way as another control I was working on at the time, which didn't work.



    The control in question was a tab control in which I needed to obtain the text on the currently selected tab and compare it with another string.  The obtain the selected tab's text in the tab control, I am using the 'text' property, i.e. tabCtrl.selectedTab.text.  It is this that doesn't work with the toString() method unless it's created as a new String, i.e. myVar = new String(tabCtrl.selectedTab.text).  Only when I do this, can I treat it as a String object and also apply the toLowerCase() method.  It must, therefore, be held as some type other than String, so your first post was very helpful in this respect, as I wasn't aware that objects could have different types.  Your second post highlighted this in that the object you instantiated explicitly as being a String works with the code whereas the other object needs a little help.  So, putting it all together, I've been able to shorten my code a litte, it now reads as:



      myVar = new String(myObject.text).toLowerCase()



    Still not as compact as the VBScript version where LCase(myObject.text) works perfectly, but still, life would be boring if we had everything!! 



    Many thanks again for your time and help.



    Regards

    Stephen.



  • sbkeenan's avatar
    sbkeenan
    Frequent Contributor
    Hi Simon



    Thank you for your reply.  It seems that I may have over-simplified the example in my original post.



    Generally what I do when writing scripts is to convert all text to lower case before performing a comparison, so, with this in mind, in VBScript I can still use something like:





    If ( LCase(textBox.wText) <> LCase(myCompareStr) ) Then

    ......

    End If





    but in JScript, I cannot use:





    if ( (textBox.wText).toLowerCase() != myCompareStr.toLowerCase() )

    {

    ......

    }





    The system stops with a Microsoft JScript runtime error 'Object doesn't support this property or method'.



    I can only get it to work by using





    var myVar = new String(textBox.wText).toString().toLowerCase();

    if ( myVar != myCompareStr.toLowerCase() )

    {

    .....

    }





    It seems as though 'textBox.wText' is held as an object on which the 'toLowerCase()' method cannot be called.  This can only happen when the object is converted to a String, which, of course, then allows the 'toLowerCase()' method to be called.



    I was just wondering if there is a shorter workaround because ultimately 'textBox.wText' is just a text property, so why is it being treated as an object?



    Regards

    Stephen.
  • simon_glet's avatar
    simon_glet
    Regular Contributor
    Glad I could help and thanks for sharing the problem's resolution.



    Sincerely
  • sbkeenan's avatar
    sbkeenan
    Frequent Contributor
    Hi Nick



    I've just had an opportunity to test the use of OleValue, as you suggested in your post, and it works beautifuly, i.e. I no longer need to create a new String object as I had previously been doing.



    Many thanks for your input.  Little titbits like this can save one a lot of time when trying to get to grips with a new language.  It's a pity you couldn't condense 15 years of experience into a post -  I get the feeling it would be most beneficial!!



    Thanks again.



    Regards

    Stephen.