質問

So I am using a function to update my values, but I can't then get them back. I see values don't get updated, but is there any way of saving them as a reference to the return of the function.

function Amphibia(wheelRadius, finsPerPropeller, propellersSpinDirection, mode) {

        this.speed = 0;
        this.mode = mode;

        var amphibiaWheel = new PropulsionUnits.Wheel(wheelRadius);
        var amphibiaPropeller = new PropulsionUnits.Propeller(finsPerPropeller, propellersSpinDirection);

        this.changeMode = function () {
            if (mode == "land") {

                mode = "water";
            }

            else if(mode == "water") {

                mode = "land";
            }

            return {

                mode: mode
            }
        }

        this.accelerate = function() {
            if(this.mode == "water"){
                this.speed += amphibiaPropeller.acceleration;
            }
            else if(this.mode == "land"){
                this.speed += 4*amphibiaWheel.acceleration;
            }
        }

        this.changePropellerSpinDirection = function() {

            amphibiaPropeller.changeSpinDirection();
        }

        return {

            speed: this.speed,
            mode: this.mode,
            changeMode: this.changeMode,
            accelerate: this.accelerate,
            changePropellerSpinDirection: this.changePropellerSpinDirection
        }

    }

So here I am experiencing problems with changing the mode and the changeMode function expression. Mode in it should refer to this.mode and then I should be able to update the value.

役に立ちましたか?

解決

mode and this.mode are not the same. In your functions you are checking/setting values on mode and this.mode, separately.

Either should work fine, as long as you're using one or the other, in the same place, the same way.

Edit

var Amphibia = function (wheelRadius, finsPerPropeller, propellersSpinDirection, mode) {

    var amphibia = this,
        MODES = { LAND : "land", WATER : "water" };

    amphibia.getMode = function () { return mode; };
    amphibia.setMode = function (val) { mode = val; };

    amphibia.changeMode = function () {
        amphibia.setMode((mode === MODES.LAND) ? MODES.WATER : MODES.LAND);
    };
};


var amphibia = new Amphibia("", "", "", "land");

amphibia.getMode();    // "land"
amphibia.changeMode();
amphibia.getMode();    // "water"

mode is now 100% private, and unique to that instance.

If you don't need it to be, then you can append it to this, if you'd like.

But here's your problem:

var Amphibia = function () {
    var amphibia = this,
        amphibiaPropeller = new Propeller(  );

    // mode, getMode, setMode, etc...

    amphibia.accelerate = function () {
        if (amphibia.getMode() === "water") {
            this.speed += amphibiaPropeller.acceleration;
        }
    };
};

var amphibia = new Amphibia();
var bob = { speed : 0 };
bob.accelerate = amphibia.accelerate;

bob.accelerate();
// if amphibia.mode === "water", bob.speed += amphibiaPropeller.acceleration

bob.speed; // === amphibiaPropeller.acceleration


setTimeout(amphibia.accelerate, 10); // call amphibia.accelerate in ~10ms
// if amphibia.mode === "water", window.speed += amphibiaPropeller.acceleration
window.speed; // === amphibiaPropeller.acceleration

Be consistent in how you refer to things.
Don't mix self and this, unless you intend to get those side-effects...
And unless you have a very, very good reason to do so (like you're building a framework/engine, not the modules/classes of the game/simulation which use the engine; ie: the difference between building jQuery and building something with jQuery), then you should probably avoid doing it.

If you have closure ("private") state that you want to expose to the outside world, all you need is a function that returns that value, and/or one that sets it.
All of a sudden, the differences between self and this and what is which, when, all go away, as long as you are consistent with how you use them, and you know what the value of this is going to be, every time you call the method.

Notice I'm not returning anything...
When I use new, the value of this (amphibia/self) gets returned by default.

If you want to use private values, and return a "Revealing Module" (which is what I typically prefer), then you can simply do this:

var Amphibia = function (mode) {
    var getMode = function () { return mode; },
        setMode = function (val) { mode = val; },
        changeMode = function () {
            setMode( mode === "water" ? "land" : "water" );
        };

    return {
        getMode : getMode,
        setMode : setMode,
        changeMode : changeMode
    };
};

var amphibia = new Amphibia("water");
// `new` won't do any harm, but you can also not use it,
// without it saving everything to `window`

amphibia.getMode(); // "water"
amphibia.changeMode();
amphibia.getMode(); // "land"

Or, maybe if you want that to look a little more like a module/component...

    return {
        mode : { get : getMode, set : setMode, switch : changeMode }
    };


var amphibia = Amphibia("land");
amphibia.mode.get(); // "land"
amphibia.mode.switch();
amphibia.mode.get(); // "water"


var bob = { };
bob.switchAmphibiaMode = amphibia.mode.switch;
bob.switchAmphibiaMode();
amphibia.mode.get(); // "land"

setTimeout(amphibia.mode.switch, 10);
setTimeout(function () { console.log(amphibia.mode.get()); }, 20);

// 10ms amphibia.mode.switch();
// 20ms console.log(amphibia.mode.get());
//          > "water"

...or whatever other structure you'd like.
You don't need a this at all.

But this is something to be very, very careful with in JavaScript, because the meaning of this changes every time you call a function, and if half of the code uses this and half uses self, you're bound for some surprises.

他のヒント

I managed to find the answer myself! :) So basicly this in the function constructor refers to Amphibia and this in the this.changeMode function expression refers to object window. Therefore we can define a variable self = this; in the constructor, so we can refer to the same thing in the function expression, as in the function. I explained it a bit awful, but here is my fixed code ;)

function Amphibia(wheelRadius, finsPerPropeller, propellersSpinDirection, mode) {

        this.speed = 0;
        var self = this;
        self.mode = mode;

        var amphibiaWheel = new PropulsionUnits.Wheel(wheelRadius);
        var amphibiaPropeller = new PropulsionUnits.Propeller(finsPerPropeller, propellersSpinDirection);

        this.changeMode = function () {


            if (self.mode == "land") {

                self.mode = "water";
            }

            else if(self.mode == "water") {

                self.mode = "land";
            }

        }

        this.accelerate = function() {
            if(self.mode == "water"){
                this.speed += amphibiaPropeller.acceleration;
            }
            else if(self.mode == "land"){
                this.speed += 4*amphibiaWheel.acceleration;
            }
        }

        this.changePropellerSpinDirection = function() {

            amphibiaPropeller.changeSpinDirection();
        }

        return {

            speed: this.speed,
            mode: this.mode,
            changeMode: self.changeMode,
            accelerate: this.accelerate,
            changePropellerSpinDirection: this.changePropellerSpinDirection
        }

    }
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top