假设我有一个这样的对象实例:
var objectA = {"a": 1, "b": 2, "c" : 3};
在我的代码中我像这样访问属性:
cc.log(objectA.a); // output 1
现在我想为这个对象添加一个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;
}
}
但是当我测试这样的函数时:
var objectA = {"a": 1, "b": 2, "c" : 3};
this.hookSetGet(objectA);
cc.log(objectA.a);
cc.log(objectA.b);
cc.log(objectA.c);
我没有得到我想要的结果:
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
答案 0 :(得分:1)
所以,你写了这个:
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;
}
}
);
来自this
的getter和setter this.hiddenValueKey
在所有情况下都指向您的objectA
对象,而不是指每个属性。因此,当您想为每个属性设置一个值时,实际上是在覆盖objectA.hiddenValueKey
。这就是为什么当您尝试get
返回值时,您只能获得设置的最后一个值。
即使您将hiddenValueKey
设置为唯一,在getter和setter中也可以访问相同的属性。这是因为this.hiddenValueKey
与撰写this['hiddenValueKey']
相同。你的意思是写this[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都是唯一的。
您可以创建一个这样的闭包:
(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));
答案 1 :(得分:0)
您的代码存在一些问题。其中之一是key
和hiddenValueKey
设置在hookGetSet
函数的范围内。因此,无论何时使用它们,都要使用循环中的最后一个值(3和__c)。您可以通过两种方式解决此问题:
let
代替var
在循环范围内定义key
和hiddenValueKey
,但这仅适用于ES6 另一个问题是,在属性中你使用this.hiddenValueKey,它与this['hiddenValueKey']
相同,而不是我认为你想要的this[hiddenValueKey]
。
这是有效的代码(EcmaScript6):
hookSetGet : function (someObject) {
for (let 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
let 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;
}
}
以下是经典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;
})();
}
}