简体   繁体   English

观察已定义属性的值时超出最大堆栈

[英]Maximum stack exceeded when observing value of defined property

I am getting a Maximum call stack size exceeded error whenever I try to use Object.observe to observe changes in an object that I defined properties for through Object.defineProperty . 每当我尝试使用Object.observe来观察我通过Object.defineProperty定义属性的对象中的更改时,都会收到“ Maximum call stack size exceeded错误。

What is the correct way to get around throwing this error while still being able to use both of these methods? 仍然可以同时使用这两种方法时,解决此错误的正确方法是什么?

Note: Object.observe is only available in Chrome and Opera 注意: 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> 

You are reading and writing to the same variable over and over again in Object.defineProperty... 您正在Object.defineProperty...Object.defineProperty...读取和写入相同的变量Object.defineProperty...

You should change the name of this.testValue in the first line of TestClass. 您应该在TestClass的第一行中更改this.testValue的名称。 I would suggest renaming it to this._testValue which is a convention for naming variables to indict they are "private". 我建议将其重命名为this._testValue ,这是命名变量以this._testValue其“私有”的约定。

Note, you can also keep this.testValue and completely remove the Object.defineProperty... section, because all you're doing is reading and writing the value, which is default. 注意,您还可以保留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> 

Another way to solve this issue, if you don't want to sort of "wrap" your value with indirection, is to use Object.getNotifier() which allows you to emit notifications manually and keep a local variable that isn't a member of your object. 解决此问题的另一种方法是,如果您不希望通过间接方式“包装”您的值,请使用Object.getNotifier() ,它允许您手动发出通知并保留不是成员的局部变量你的对象。

If you use the notifier you can get around having to have object properties that won't actually be used. 如果使用通知程序,则可以避免必须具有实际上不会使用的对象属性。 If you use the wrapping method, you will have both _testValue and testValue on the object. 如果使用包装方法,则对象上将同时具有_testValue testValue Using the notifier, you will only have testValue . 使用通知程序,您将只有 testValue

Consider the code change: 考虑代码更改:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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