0

through のプロパティを定義したオブジェクトの変更を観察するためにを使用しようとすると、Maximum call stack size exceededエラーが発生します。Object.observeObject.defineProperty

これらの両方の方法を引き続き使用しながら、このエラーをスローするのを回避する正しい方法は何ですか?

注:Object.observeは Chrome と Opera でのみ利用可能です

var TestModule = (function () {
    "use strict";

    function TestClass() {
        this.testValue = 0;
        Object.defineProperty(this, "testValue", {
            get: function () {
                return this.testValue;
            },
            set: function (value) {
                this.testValue = value;
            },
            enumerable: true,
            configurable: false
        });
    }

    return {
        TestClass: TestClass
    };
}());
<!DOCTYPE html>

<head>
    <title>Stack Exceed Test</title>
    <script src="../js/TestModule.js"></script>
</head>

<body>
    <main>
        <div id="logger" role="log"></div>
    </main>
    <script>
        document.addEventListener("DOMContentLoaded", function () {
            var logger = document.getElementById("logger"),
                tc = new TestModule.TestClass();

            function log(message) {
                if (logger) {
                    logger.innerHTML = message;
                } else {
                    console.error(message);
                }
            }

            if (typeof Object.observe === "function") {
                Object.observe(tc, function (changes) {
                    console.log("Change");
                });

                try {
                    tc.testValue = 5;
                } catch (e) {
                    log(e);
                }
            } else {
                log("Object.observe is unsupported in your browser");
            }
        });
    </script>
</body>

4

2 に答える 2

1

同じ変数を何度も読み書きしていますObject.defineProperty...

this.testValueTestClass の最初の行の名前を変更する必要があります。this._testValue変数に名前を付けて「プライベート」であることを示すための規則である名前に変更することをお勧めします。

デフォルトの値を読み書きするだけなので、セクションを保持this.testValueして完全に削除することもできます。Object.defineProperty...

var TestModule = (function () {
    "use strict";

    function TestClass() {
        this._testValue = 0;
        Object.defineProperty(this, "testValue", {
            get: function () {
                return this._testValue;
            },
            set: function (value) {
                this._testValue = value;
            },
            enumerable: true,
            configurable: false
        });
    }

    return {
        TestClass: TestClass
    };
}());
<!DOCTYPE html>

<head>
    <title>Stack Exceed Test</title>
    <script src="../js/TestModule.js"></script>
</head>

<body>
    <main>
        <div id="logger" role="log"></div>
    </main>
    <script>
        document.addEventListener("DOMContentLoaded", function () {
            var logger = document.getElementById("logger"),
                tc = new TestModule.TestClass();

            function log(message) {
                if (logger) {
                    logger.innerHTML = message;
                } else {
                    console.error(message);
                }
            }

            if (typeof Object.observe === "function") {
                Object.observe(tc, function (changes) {
                    console.log("Change");
                });

                try {
                    tc.testValue = 5;
                } catch (e) {
                    log(e);
                }
            } else {
                log("Object.observe is unsupported in your browser");
            }
        });
    </script>
</body>

于 2015-09-15T17:57:17.607 に答える
0

この問題を解決する別の方法として、値を間接的に「ラップ」したくない場合は、Object.getNotifier()手動で通知を発行し、オブジェクトのメンバーではないローカル変数を保持できるようにする方法を使用します。

通知機能を使用すると、実際には使用されないオブジェクト プロパティを持つ必要がなくなります。_testValue ラッピング方法を使用すると、オブジェクトにと の両方がtestValue含まれます。通知機能を使用するtestValue.

コードの変更を検討してください。

function TestClass() {
    var testValue, notifier;
    /* 
     * The new locally scoped varible which will
     * be captured by the getter/setter closure
     */
    testValue = 0;

    /*
     * Create a notifier for the object
     * which we can use to trigger 
     * Object.observe events manually
     */
    notifier = Object.getNotifier(this);

    Object.defineProperty(this, "testValue", {
        get: function () {
            return testValue;
        },
        set: function (value) {
            /*
             * Use the notifier to trigger 
             * the observe()
             */
            notifier.notify({
                type: "update",
                name: "testValue",
                oldValue: testValue
            });
            testValue = value;
        },
        enumerable: true,
        configurable: false
    });
}
于 2015-09-15T19:44:23.643 に答える