观察定义值 属性 时超出最大堆栈
Maximum stack exceeded when observing value of defined property
每当我尝试使用 Object.observe
to observe changes in an object that I defined properties for through Object.defineProperty
.
时,我都会收到 Maximum call stack size exceeded
错误
在仍然能够使用这两种方法的同时避免抛出此错误的正确方法是什么?
注意: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>
您在 Object.defineProperty...
中一遍又一遍地读写同一个变量
您应该在 TestClass 的第一行更改 this.testValue
的名称。我建议将其重命名为 this._testValue
,这是命名变量的约定,以表明它们是 "private".
注意,您也可以保留 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>
另一种解决此问题的方法,如果您不想通过间接方式对 "wrap" 您的值进行排序,是使用 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
});
}
每当我尝试使用 Object.observe
to observe changes in an object that I defined properties for through Object.defineProperty
.
Maximum call stack size exceeded
错误
在仍然能够使用这两种方法的同时避免抛出此错误的正确方法是什么?
注意: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>
您在 Object.defineProperty...
您应该在 TestClass 的第一行更改 this.testValue
的名称。我建议将其重命名为 this._testValue
,这是命名变量的约定,以表明它们是 "private".
注意,您也可以保留 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>
另一种解决此问题的方法,如果您不想通过间接方式对 "wrap" 您的值进行排序,是使用 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
});
}