简体   繁体   中英

OOP Javascript, Why this object doesn't work like expected?

What do I want to achieve?

I have an class called Looper. I want to give each object a name and an own looper.

Results I expect

Created Looper Object...
one
Created Looper Object...
two
one - 1
two - 1
one - 2
two - 2
one - 3
two - 3
one - 4
two - 4
one - 5
two - 5
.......

My code

With this code I expect it to work..

var Looper = (function (window, document, $) {

    this.i = 1;

    var Looper = function () {
        console.log('Created Looper Object...');
    }

    var getName = function () {
        return this.name;
    }

    var setName = function (newName) {
        this.name = newName;
    }

    var loop = function () {
        console.log(getName() + ' - ' + this.i);
        this.i = this.i + 1;
    }

    var startLoop = function () {
        window.setInterval(loop, 1000);
    }

    Looper.prototype = {
        getName: getName,
        setName: setName,
        start: startLoop
    }

    return Looper;
})(window, document, jQuery);

var one = new Looper();
one.setName('one');
console.log(one.getName());
one.start();

var two = new Looper();
two.setName('two');
console.log(two.getName());
two.start();

jsFiddle example

My results

But it doesn't....

Created Looper Object...
one
Created Looper Object...
two
result - 1
result - 2
result - 3
result - 4
result - 5
.......

Can someone tell me why it doesn't?

My problem is that is can set this.name for each object.

But I cannot set this.i for each object. They overtake each others i . Looks like this.i is static?!?!?

Also when I use console.log(two.getName()); it works. But within the loop this.name is result ?

You need to create the this.i = 1; property inside of the constructor function:

var Looper = function () {
    this.i = 1;
    console.log('Created Looper Object...');
}

In your current code the this keyword refers to the global object ( window ), so that you are actually creating a global variable (which is some kind of "static", yes).

A similar thing happens in the function called from setInterval , this is again set to the global object (that's the reason why it finds the number at all). You need to explicitly call your loop method on the Looper instance, for example by

var startLoop = function () {
    var that = this;
    window.setInterval(function() {
       loop.call(that); // "that" refers to the Looper object, while "this" does not
       // if "loop" were a method on the Looper, it's equivalent to
       // that.loop()
    }, 1000);
}

or via bind

var startLoop = function () {
    window.setInterval(loop.bind(this), 1000);
}

Also, inside the loop function you will need to call getName as a method on the current Looper object:

this.getName()

It seems to add a little confusion that all your functions/methods are not only accessible on (inherited) properties of the objects, but also as local variables in your module. Notice that JavaScript has no classes , and this does not work like in Java - you always need to explicitly distinguish between variables and properties. Your module should look more like this:

var Looper = (function() {

    function Looper() {
        this.i = 1;
        this.name = null;
        console.log('Created Looper Object:', this);
    }

    Looper.prototype.getName = function() {
        return this.name;
    };
    Looper.prototype.setName = function(newName) {
        this.name = newName;
    };
    Looper.prototype.start = function() {
        var that = this;
        window.setInterval(function() {
            console.log(that.getName() + ' - ' + that.i);
            that.i++;
        }, 1000);
    };

    return Looper;
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM