Himmators
Himmators

Reputation: 15006

How should I deal with properties inside anonymous functions inside javascript classes?

I'm new to object-oriented javascript so maybe I got the terminology wrong.

I have a javascript class that looks like this.

var parsesearch = {
    init: function(selector){
        this.selector = $(selector);
        this.count = $(selector).length;
    },
    loopresluts: function(selector){
        this.delay = 350
        this.selector.each(function(indexInArray) {
            parsesearch.announcementID = parsesearch.selector.find('[headers=h-diarienummer] a').text();
            //opening the pages with a delay
            setTimeout( function () {
                console.log(parsesearch.announcementID)
            //adding delay for every itteration.
            }, indexInArray * parsesearch.delay);
        });
    }
}

Inside loopresults I have an anonymous function. Inside that function i can't use "this" to reference the properties, but rather use parsesearch."propertyname" I assume that if I instance more than one version of parsesearch, this will cause trouble. Is there a better way to do it? If I use only one instance of the class, would this be considered bad practice, in that case why?

Upvotes: 2

Views: 91

Answers (5)

Entity Black
Entity Black

Reputation: 3491

Whoa so many questions. Let's take it step by step. When you started with

var parsesearch = { ...

you did singleton, so you can't basicly do more instances of parsesearch. You have just one instance and its functions, thats all.

If I use only one instance of the class, would this be concidered bad practice, in that case why?

It depends what is its purpose. If you will extend this "widget" and you will add something like options and other stuff + you will want use more widgets on one site, then you will probably need more instances. Till then, it is ok to have only one instance and you can keep it like it is.

About this question, I basicly agree with zaquest and *Thanassis_K* answers. You can use call, apply native functions or jQuery proxy function to change this of desired function. Also var self = this is very common practise. Then self is variable of namespace. Anyway, for some reson all answers here are avoiding prototype, which should be used here, becouse if you declare functions as simple object properties, then they are redeclared with every new instance, which is waste...

My solution for more instances

var ParseSearch = function (selector) {
    this.selector = $(selector);
    this.count = $(selector).length;
    this.delay = 350;
}

// you dont need init here... 

ParseSearch.prototype.loopresluts = function(){
    this.selector.each($.proxy(function(indexInArray) {
        this.announcementID = this.selector.find('[headers=h-diarienummer] a')
                                           .text();
        //opening the pages with a delay
        setTimeout($.proxy(function () {
            console.log(this.announcementID)
        //adding delay for every itteration.
        }, this), indexInArray * this.delay);
    }, this));
}

var firstParser = new ParseSearch('div');
firstParser.loopresluts();

Upvotes: 1

akakarikos
akakarikos

Reputation: 450

You could modify it to the following:

 var parsesearch = (function () {
    var init = function (selector) {
        this.selector = $(selector);
        this.count = $(selector).length;
    }
    var loopresluts = function (selector) {
        var self = this; // self now refers to that function only
        this.delay = 350
        this.selector.each(function (indexInArray) {
            parsesearch.announcementID = parsesearch.selector.find('[headers=h-diarienummer] a').text();
            //opening the pages with a delay
            setTimeout(function () {
                console.log(parsesearch.announcementID)
                //adding delay for every itteration.
            }, indexInArray * parsesearch.delay);
        });
    }
    return {
        init: init,
        loopresluts: loopresluts
    }
});

// create a single instance of your object
var parseS = parsesearch();

Upvotes: 0

zaquest
zaquest

Reputation: 2050

The simplest way to do this is using closures

var parsesearch = {
    init: function(selector){
        this.selector = $(selector);
        this.count = $(selector).length;
    },
    loopresluts: function(selector){
        var self = this;
        this.delay = 350
        this.selector.each(function(indexInArray) {
            self.announcementID = self.selector.find('[headers=h-diarienummer] a').text();
            //opening the pages with a delay
            setTimeout( function () {
                console.log(self.announcementID)
            //adding delay for every itteration.
            }, indexInArray * self.delay);
        });
    }
}

or, since you already using jQuery you can use jQuery.proxy

var parsesearch = {
    init: function(selector){
        this.selector = $(selector);
        this.count = $(selector).length;
    },
    loopresluts: function(selector){
        this.delay = 350
        this.selector.each($.proxy(function(indexInArray) {
            this.announcementID = this.selector.find('[headers=h-diarienummer] a').text();
            //opening the pages with a delay
            setTimeout($.proxy(function () {
                console.log(this.announcementID)
            //adding delay for every itteration.
            }, this), indexInArray * this.delay);
        }, this));
    }
}

Upvotes: 1

Brigand
Brigand

Reputation: 86240

Bind Method

You can bind a function to an object, e.g., this

var parsesearch = {
    init: function(selector){
        this.selector = $(selector);
        this.count = $(selector).length;
    },
    loopresluts: function(selector){
        this.delay = 350
        this.selector.each((function(indexInArray) {
            this.announcementID = this.selector.find('[headers=h-diarienummer] a').text();
            //opening the pages with a delay
            setTimeout( function () {
                console.log(this.announcementID)
            //adding delay for every itteration.
            }, indexInArray * this.delay);
        }).bind(this));
    }
}

Scope Method

By declaring a local variable that references this, you can then use that variable inside nested functions.

var parsesearch = {
    ...
    loopresluts: function(selector){
        var p = this;
        this.delay = 350
        this.selector.each(function(indexInArray) {
            p.announcementID = p.selector.find('[headers=h-diarienummer] a').text();
            //opening the pages with a delay
            setTimeout( function () {
                console.log(p.announcementID)
            //adding delay for every itteration.
            }, indexInArray * p.delay);
        });
    }
}

Upvotes: 0

Louis Ricci
Louis Ricci

Reputation: 21086

You just use a variable to hold the current instance (this), than it will be in scope for the anonymous functions to use.

loopresluts: function(selector){
    this.delay = 350;
    var scoped = this;
    this.selector.each(function(indexInArray) {
        scoped.announcementID = parsesearch.selector.find('[headers=h-diarienummer] a').text();
        //opening the pages with a delay
        setTimeout( function () {
            console.log(scoped.announcementID)
        //adding delay for every itteration.
        }, indexInArray * scoped.delay);
    });
}

Upvotes: 0

Related Questions