2

好吧,让我解释一下我要做什么,感觉像是一个基本问题,但似乎很难解决:假设我有一个常规的 javascript 对象:

var x = {};

现在,当我向 object 添加任何新属性(让我们newProp现在使用)时x,我想在存储它时通过父对象的函数自动传递该新属性及其值:initializerx

x.initializer = function(propKey, propValue){
  console.log(propKey, 'IS', propValue);
}

x.newProp = 13;

所以在这种情况下,我想x.initializer(x.newProp);在我定义时自动触发x.newProp(AND 作为奖励,任何时候我分配/更改它的值。)但最终,我希望对添加到x.

我曾尝试通过 setter/getter 和原型来做到这一点,但这些方法的复杂性并不明显并且似乎有限。

例如,即使我做这样的事情:

function setterFunc(value){
  x.initializer("newProp", value); //the name of the property isn't even dynamic.
}
function getterFunc(value){
  return someValue; //SOMEHOW!
}
Object.defineProperty(x, 'newProp', { get: getterFunc,
                                      set: setterFunc,
                                      configurable: true,
                                      enumerable: true });

这种方法存在许多问题/并发症:

  1. 由于使用 get/set 的性质,newProp 的值需要存储在另一个键中。
  2. 新属性的名称是模糊的,只有值可以传递给初始化函数(据我所知)。
  3. 即使使用 getter 函数,检索原始存储值也很复杂,并且需要某种索引或其他东西。
  4. 不知何故,通过 x 的原型为所有新属性实现这一点似乎很疯狂......是吗?我什至不知道这是否可能。

任何帮助都非常感谢......我很茫然!如果需要,我会澄清。


更新

有很多建议,但似乎从未完全给出完整的答案。经过几个月和一些启示,这里有一些候选人(尽管没有一个是完全最佳的):

代理人

http://wiki.ecmascript.org/doku.php?id=harmony:direct_proxies

由 Rob W 建议,似乎与所需功能非常匹配。如前所述,它并没有在所有地方实施,并且仍然是和谐草案的一部分。


对象.observe();

http://wiki.ecmascript.org/doku.php?id=harmony:observe

此外,作为和谐规范的一部分,Observe 以最小的性能影响(理论上)监听对象的变化。也是一条路。


Watch.js

https://github.com/melanke/Watch.JS

这个跨浏览器库监视对象的属性,但它似乎并不监视对象本身。因此,您似乎必须将要监视的对象分配给另一个对象的属性。

4

1 回答 1

3

问题 2 可以通过为每个属性生成不同的 getter 和 setter 函数来解决。

function setterFunc(prop) {
  return function(value) {
    x._private[prop] = value;
    x.initializer(prop, value);
  }
}

function getterFunc(prop) {
  return function() {
    return x._private[prop];
  }
}

Object.defineProperty(x, 'newProp', { get: getterFunc('newProp'),
                                      set: setterFunc('newProp'),
                                      configurable: true,
                                      enumerable: true });
于 2013-08-05T20:59:36.617 回答