Javascript Object.defineProperty get set返回错误的值
假设我有这样一个对象实例:Javascript Object.defineProperty get set返回错误的值,javascript,Javascript,假设我有这样一个对象实例: var objectA = {"a": 1, "b": 2, "c" : 3}; 在我的代码中,我访问属性的方式如下: cc.log(objectA.a); // output 1 var objectA = {"a": 1, "b": 2, "c" : 3}; this.hookSetGet(objectA); cc.log(objectA.a); cc.log(objectA.b); cc.log(objectA.c); (function(hidd
var objectA = {"a": 1, "b": 2, "c" : 3};
在我的代码中,我访问属性的方式如下:
cc.log(objectA.a); // output 1
var objectA = {"a": 1, "b": 2, "c" : 3};
this.hookSetGet(objectA);
cc.log(objectA.a);
cc.log(objectA.b);
cc.log(objectA.c);
(function(hiddenValueKey) {
Object.defineProperty (
someObject,
key,
{
set: function (val) {
// simulate encrypt
this[hiddenValueKey] = val + 1;
cc.log("hooked set: " + val + " - " + this[hiddenValueKey]);
},
get: function () {
cc.log("hooked get: " + this[hiddenValueKey] + " - " + (this[hiddenValueKey] - 1));
// simulate decrypt
return this[hiddenValueKey] - 1;
}
}
);
}(hiddenValueKey));
现在,我想为该对象添加一个get/set,以提供一些简单的加密/解密功能:
hookSetGet: function (someObject) {
for (var key in someObject) {
cc.log("key: " + key);
// store the origin value before Object.defineProperty
var pureValue = someObject[key];
// add a property to store the encrypted value
var hiddenValueKey = "__" + key;
someObject[hiddenValueKey] = undefined;
Object.defineProperty (
someObject,
key,
{
set: function (val) {
// simulate encrypt
this.hiddenValueKey = val + 1;
cc.log("hooked set: " + val + " - " + this.hiddenValueKey);
},
get: function () {
cc.log("hooked get: " + this.hiddenValueKey + " - " + (this.hiddenValueKey - 1));
// simulate decrypt
return this.hiddenValueKey - 1;
}
}
);
// trigger set to encrypt
someObject[key] = pureValue;
}
}
但是当我像这样测试函数时:
cc.log(objectA.a); // output 1
var objectA = {"a": 1, "b": 2, "c" : 3};
this.hookSetGet(objectA);
cc.log(objectA.a);
cc.log(objectA.b);
cc.log(objectA.c);
(function(hiddenValueKey) {
Object.defineProperty (
someObject,
key,
{
set: function (val) {
// simulate encrypt
this[hiddenValueKey] = val + 1;
cc.log("hooked set: " + val + " - " + this[hiddenValueKey]);
},
get: function () {
cc.log("hooked get: " + this[hiddenValueKey] + " - " + (this[hiddenValueKey] - 1));
// simulate decrypt
return this[hiddenValueKey] - 1;
}
}
);
}(hiddenValueKey));
我没有得到我想要的结果:
key: a
hooked set: 1 - 2
key: b
hooked set: 2 - 3
key: c
hooked set: 3 - 4
hooked get: 4 - 3
3
hooked get: 4 - 3
3
hooked get: 4 - 3
3
甚至当我打电话的时候
objectA.a
我将得到的价值
objectA.c
这个问题似乎很简单,但我就是想不出哪里错了
如有任何建议,将不胜感激,谢谢:)
更新:
我尝试了以下代码,但没有更改hookSetGet的代码:
cc.log(objectA.__a);
cc.log(objectA.__b);
cc.log(objectA.__c);
并获得:
undefined
undefined
undefined
然后我更改了hookSetGet函数:
set: function (val) {
// simulate encrypt
someObject[hiddenValueKey] = val + 1;
cc.log("hooked set: " + val + " - " + someObject[hiddenValueKey]);
},
get: function () {
cc.log("hooked get: " + someObject[hiddenValueKey] + " - " + (someObject[hiddenValueKey] - 1));
// simulate decrypt
return someObject[hiddenValueKey] - 1;
}
我将所有this.hiddenValueKey更改为someObject[hiddenValueKey]
输出为:
cc.log(objectA.__a); // 2 good
cc.log(objectA.__b); // 3 good
cc.log(objectA.__c); // 4 good
cc.log(objectA.a); // hooked get: 4 - 3 still wrong
cc.log(objectA.b); // hooked get: 4 - 3 still wrong
cc.log(objectA.c); // hooked get: 4 - 3 still wrong
所以,你写了这个:
Object.defineProperty (
someObject,
key,
{
set: function (val) {
// simulate encrypt
this.hiddenValueKey = val + 1;
cc.log("hooked set: " + val + " - " + this.hiddenValueKey);
},
get: function () {
cc.log("hooked get: " + this.hiddenValueKey + " - " + (this.hiddenValueKey - 1));
// simulate decrypt
return this.hiddenValueKey - 1;
}
}
);
在您的getter和setter中,this
fromthis.hiddenValueKey
在所有情况下都引用您的对象a
对象,而不是每个属性。因此,当您想要为每个属性设置一个值时,实际上是在重写objectA.hiddenValueKey
。这就是为什么当您尝试获取
返回值时,您只能获取最后设置的值
即使将hiddenValueKey
设置为唯一,在getter和setter中也可以访问相同的属性。这是因为This.hiddenValueKey
与编写This['hiddenValueKey']
相同。你是想写这个[hiddenValueKey]?即使这样做,退出循环后,hiddenValueKey
始终具有最新的键值也可能会出现一些范围问题
因此,您可以尝试以下方法:
Object.defineProperty (
someObject,
key,
{
set: function (val) {
// simulate encrypt
this[hiddenValueKey] = val + 1;
cc.log("hooked set: " + val + " - " + this[hiddenValueKey]);
},
get: function () {
cc.log("hooked get: " + this[hiddenValueKey] + " - " + (this[hiddenValueKey] - 1));
// simulate decrypt
return this[hiddenValueKey] - 1;
}
}
);
但是,正如我所说的,您可能必须为hiddenValueKey
变量创建一个闭包,以便它对于每个属性getter和setter都是唯一的
可以创建如下所示的闭包:
cc.log(objectA.a); // output 1
var objectA = {"a": 1, "b": 2, "c" : 3};
this.hookSetGet(objectA);
cc.log(objectA.a);
cc.log(objectA.b);
cc.log(objectA.c);
(function(hiddenValueKey) {
Object.defineProperty (
someObject,
key,
{
set: function (val) {
// simulate encrypt
this[hiddenValueKey] = val + 1;
cc.log("hooked set: " + val + " - " + this[hiddenValueKey]);
},
get: function () {
cc.log("hooked get: " + this[hiddenValueKey] + " - " + (this[hiddenValueKey] - 1));
// simulate decrypt
return this[hiddenValueKey] - 1;
}
}
);
}(hiddenValueKey));
您的代码有几个问题。其中之一是在
hookGetSet
函数的范围内设置key
和hiddenValueKey
。因此,无论何时使用它们,都会使用循环中的最后一个值(3和__c)。您可以通过两种方式解决此问题:
- 使用
而不是let
在循环范围内定义var
和key
,但这仅适用于ES6hiddenValueKey
- 使用闭包来确定循环内部的范围
this['hiddenValueKey']
相同,而不是我假设您想要的这个[hiddenValueKey]
以下是有效的代码(ECMAScript 6):
下面是与经典ES5 Javascript相同的代码:
hookSetGet : function (someObject) {
for (var k in someObject) {
(function () {
var key = k;
cc.log("key: " + key);
// store the origin value before Object.defineProperty
var pureValue = someObject[key];
// add a property to store the encrypted value
var hiddenValueKey = "__" + key;
someObject[hiddenValueKey] = undefined;
Object.defineProperty(
someObject,
key, {
set : function (val) {
// simulate encrypt
this[hiddenValueKey] = val + 1000;
cc.log("hooked set: " + val + " - " + this[hiddenValueKey]);
},
get : function () {
// simulate decrypt
var result = this[hiddenValueKey] - 1000;
cc.log("hooked get: " + this[hiddenValueKey] + " - " + result);
return result;
}
});
// trigger set to encrypt
someObject[key] = pureValue;
})();
}
}
在枚举对象时修改对象是否明智?@MatthewHerbst:是的,这不重要,属性不会重复两次。可能重复,谢谢你的帮助:)现在一切正常:)