javascript object question

I’ve got the following code:

var parser = {
    stop: [],
    useSegments: true,

    extract: function(s){ .... },

    parse: function(){
        if(this.useSegments){
            ....
        }
        var _words = this.extract(s);
        this.stop = _words;
}

I’ve got buildmarkers on the last 2 lines and not on if(this.useSegments).
But when I remove the if(this.useSegments) lines, then the other buildmarkers are gone.
Why is that?

Note: this is only part of my parser object ofcourse, and I can succesfully use both the stop variable and the extract function in other parts of the object.

Hi Jos,

What does the build marker say?
Also what is inside the if statement ?

I think the question really is why there is no buildmarker at this line:

if(this.useSegments){

Any particular reason why not using a constructor function? That way the object is really aware of its own properties and methods and you have nice code completion.

function Parser() {
	var parser = this;
	
	this.stop = [],
	this.useSegments = true;
	this.extract = function(s) { }
	this.parse = function() {
		if (parser.useSegments) {

		}
		var _words = parser.extract(s);
		parser.stop = _words
	}
}

Unfortunately, in general Servoy is not that clever in figuring out what ‘this’ refers to. You can fix that by using the @this tag on functions.

Seem like this is scheduled to be fixed in 8.1, see https://support.servoy.com/browse/SVY-4203

Paul

@Robert:
the buildmarker: “The method extract() is undefined for object”
and inside the if statement I set a local variable, not very exciting stuff.

I noticed that when I change my code to:

var _b = this.useSegments;
if(_b){ }

All the builmarkers are gone.

@Ruben:
I haven’t used objects very often, and this is the only way i’ve used them before. Is your solution really better? Or just another way of doing things?

@Paul:
Is that maybe why using a local var to store the value in removes the buildmarkers (like in my code sample above) ?

Hi Jos,

After really looking at your code I am with Ruben on this (no pun intended) with the addition to add a ‘return this’ at the end :)

function Parser() {
   var parser = this; // Use the variable in deeper structures inside this object
   
   this.stop = [];
   this.useSegments = true;
   this.extract = function(s) { }
   this.parse = function() {
      // this is a deeper structure, now reference the main function with the 'parser' variable
      if (parser.useSegments) {

      }
      var _words = parser.extract(s);
      parser.stop = _words;
   }
   return this;
}

Now you can use this object with proper code completion like so:

var myParser = Parser();
myParser.parse(myValue);

// or as a oneliner
Parser().parse(myValue);

Hope this helps.

Another way of working with this in deeper/other scopes is to actually pass it.
Also referencing code outside of the object that you instantiate is also more memory efficient instead of encapsulating it all inside.
Look at this timer object as an example:

function getTimer() {
    var _sPrefix = "Timer: ",
        initDate = new Date();

    function checkState(that) {
        if (!that.startDate) {
            throw new Error("Timer has already been stopped");
        }
    }

    function stopTimer(desc, that) {
        var curDate = new Date(),
            _sComment = (desc !== undefined ? "[" + desc + "] " : "");
        checkState(that);
        if (that.lapseDate != that.startDate) {
            application.output(_sPrefix + _sComment + "Lapse-time: " + (curDate - that.lapseDate) + " ms, Total time: " + (curDate - that.startDate) + " ms", LOGGINGLEVEL.DEBUG);
        } else {
            application.output(_sPrefix + _sComment + (new Date() - that.startDate) + " ms", LOGGINGLEVEL.DEBUG);
        }
        that.startDate = null;

    }

    function lapseTimer(desc, that) {
        var curDate = new Date(),
            _sComment = (desc !== undefined ? "[" + desc + "] " : "");
        checkState(that);
        application.output(_sPrefix + _sComment + "Lapse-time: " + (curDate - that.lapseDate) + " ms, Total time: " + (curDate - that.startDate) + " ms", LOGGINGLEVEL.DEBUG);
        that.lapseDate = curDate;
    }

    return {
        /**
         * @protected
         */
        startDate: initDate,
        /**
         * @protected
         */
        lapseDate: initDate,
        /**
         * @type {String} [comment]
         */
        lapsetime: function(comment) {
            lapseTimer(comment, this);
        },
        /**
         * @type {String} [comment]
         */
        stop: function(comment) {
            stopTimer(comment, this);
        }
    }
}

Usage:

var _oTimer = getTimer(); // this starts the timer as well

//  your code

_oTimer.stop(); // outputs the time it took to run your code

Thank you Robert.
I’ll have a look at that.