【问题标题】:Updating values with a function, returning not working用函数更新值,返回不工作
【发布时间】:2014-02-18 22:40:57
【问题描述】:

所以我正在使用一个函数来更新我的值,但我无法将它们取回。我看到值没有得到更新,但有没有办法将它们保存为对函数返回的引用。

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
        }

    }

所以在这里我遇到了更改模式和 changeMode 函数表达式的问题。其中的模式应该引用this.mode,然后我应该能够更新该值。

【问题讨论】:

    标签: javascript closures function-expression


    【解决方案1】:

    modethis.mode 相同。在您的函数中,您分别检查/设置 modethis.mode 的值。

    只要您在同一个地方以同样的方式使用其中一个或另一个,任何一个都应该可以正常工作。

    编辑

    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 现在是 100% 私有的,并且对于该实例是唯一的。

    如果您不需要,可以将其附加到this,如果您愿意的话。

    但这是你的问题:

    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
    

    在引用事物的方式上保持一致。
    不要混用 selfthis,除非您打算获得这些副作用...
    除非你有非常非常好的理由这样做(比如你正在构建一个框架/引擎,而不是使用引擎的游戏/模拟的模块/类;即:差异在构建 jQuery 和构建 with jQuery 之间),那么你应该避免这样做。

    如果您有想要向外界公开的闭包(“私有”)状态,您只需要一个返回该值的函数,和/或设置它的函数。
    一下子,selfthis 的区别,what is which,when,都消失了,只要你的使用方式一致,你知道this 的价值在哪里每次您调用该方法时。

    请注意,我不会退回任何东西...
    当我使用new 时,默认返回this (amphibia/self) 的值。

    如果你想使用私有值,并返回一个“显示模块”(这是我通常喜欢的),那么你可以简单地这样做:

    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"
    

    或者,如果您希望它看起来更像一个模块/组件...

        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"
    

    ...或您想要的任何其他结构。
    你根本不需要this

    但是this 在 JavaScript 中是非常非常小心的,因为每次调用函数时this 的含义都会发生变化,如果一半代码使用this 而一半使用self ,你一定会遇到一些惊喜。

    【讨论】:

    • 当我在 this.changeMode 函数表达式中记录 this.mode 时,它​​返回 undefined,所以我想我不能只使用 this.mode,并且不能使用变量 this。以后我不能将它从模块中返回...
    • @user3127242 如果您没有在代码中调用new Amphibia,那么this === window; 很糟糕。此外,如果您没有调用var myAmphibia = new Amphibia(/*...*/); myAmphibia.accelerate();,而是在回调中填充.accelerate (setTimeout(myAmphibia.accelerate, 0);),那么this === window;。这两个都非常不好。你的模块充满了mode; self.mode; this.mode;,它不应该是。这是一个 constructor new Amphibia( ); ,其中this 是可以接受的,或者它是一个 functionthis 不是。有例外,但规则是第一位的。
    • @user3127242 另外,当您创建var self = this; 时,它是构建时的this。当您在方法中使用this 时:if (self.mode /*...*/) { this.mode; } 您是在说“如果初始对象的模式......然后设置调用对象的模式......”不能保证它们是同一个对象。
    • @user3127242 请参阅上面的编辑,了解为什么您当前的解决方案在不久的将来仍然会爆发。
    【解决方案2】:

    我自己找到了答案! :) 所以基本上函数构造函数中的 this 指的是 Amphibia,而 this.changeMode 函数表达式中的 this 指的是对象窗口。因此我们可以定义一个变量 self = this;在构造函数中,所以我们可以在函数表达式中引用相同的东西,就像在函数中一样。我解释的有点糟糕,但这是我的固定代码;)

    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
            }
    
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多