[英]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.