我有一个名为status
的对象,我想跟踪一个班级的任何状态
除了设置各种状态,我还想跟踪这些状态的活动时间。现在,不是为每个状态定义第二个属性来跟踪时间,而是为getter / setter
的工作。
那就是我被困住的地方。如何使它们动态化,以便触发status
的每个属性?
var Person = function(options) {
this.name = options.name;
var _statusChanged = {};
var _status = {};
// How to make this dynamic?
var expr = "isOnfire";
this.status = {
get [expr]() {
console.log(_statusChanged);
return _status[expr];
},
set [expr](val) {
_status[expr] = val;
_statusChanged[expr] = new Date();
return _status[expr];
}
};
};
var John = new Person({
name: "John"
});
John.status.isOnfire = true;
John.status.hasPinkShirt = true;
console.log(John, John.status.isOnfire, John.status.hasPinkShirt);
答案 0 :(得分:1)
如果您有这些列表,只需在循环中创建getters / setter,例如:
this.status = {};
["isOnFire", "hasPinkShirt"].forEach((name) => {
Object.defineProperty(status, name {
get() {
console.log(_statusChanged);
return _status[name];
},
set(val) {
_status[name] = val;
_statusChanged[name] = new Date();
return _status[name];
}
});
});
如果他们可以任何,那么您将需要使用Proxy
object。使用代理,您可以在不事先知道属性名称的情况下捕获所有获取/设置:
this.status = new Proxy(_status, {
get(target, propKey, receiver) {
// handle get
return _status[propKey];
},
set(target, propKey, value, receiver) {
// handle set
_status[propKey] = value;
_statusChanged[propKey] = new Date();
return true; // Tells the proxy the assignment worked
}
});
(或者您可能会使用Reflect.get
和Reflect.set
,但即使Firefox还没有它们。)
Here's an article更详细地进入代理。
这是一个示例,但您需要在最新版本的Firefox中运行它,因为support or Proxy
in the wild在地面上仍然非常薄,而且就其性质而言,您无法填充/填充代理。< / p>
(function() {
"use strict";
var _status = {};
var _statusChanged = {};
var status = new Proxy(_status, {
get(target, propKey, receiver) {
snippet.log(propKey + " requested");
return _status[propKey];
},
set(target, propKey, value, receiver) {
snippet.log(propKey + " set to " + value);
_status[propKey] = value;
_statusChanged[propKey] = new Date();
return true; // Tells the proxy the assignment worked
}
});
status.foo = "bar";
snippet.log("foo = " + status.foo);
})();
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
在您可以使用它们之前,您需要将状态设置为方法调用,而不是分配。
答案 1 :(得分:0)
您需要一个名为ECMAScript 6 Proxy
的对象。在Firefox中,它们默认处于启用状态。有一次,他们是在“experimental JavaScript”下的Chrome中实现的,但它们似乎暂时被删除了;见this ES6 compatibility table。
此代码适用于Firefox:
var output = function(text) {
var line = document.createElement('div');
line.innerHTML = text;
document.getElementById('output').appendChild(line);
}
var Person = function(options) {
this.name = options.name;
var _status = {};
var _statusChanged = {};
this.status = new Proxy(_status,{
get: function(target,property) {
return target[property];
},
set: function(target,property,value) {
_statusChanged[property] = new Date();
output("set " + property + " to " + value + " at " + _statusChanged[property]);
_status[property] = value;
}
});
this.show = function(property) {
output("Property " + property + " is " + _status[property] + " since " + _statusChanged[property]);
}
};
var John = new Person({
name: "John"
});
John.status.isOnfire = true;
John.status.hasPinkShirt = true;
John.show("isOnfire");
John.show("hasPinkShirt");
<div id="output"></div>
答案 2 :(得分:0)
也许这对你有用
http://jsfiddle.net/oksbLyqf/16/
var Person = function (options) {
this.name = options.name;
var _statusChanged = {};
var _status = {};
var expr = '';
var addStatusProperty = function (prop) {
expr = prop;
Object.defineProperty(otherStatus, expr, {
get: function () {
console.log(_statusChanged);
return _status[expr];
},
set: function (val) {
_status[expr] = val;
_statusChanged[expr] = new Date();
return _status[expr];
}
});
};
var setStatusProperty = function (prop, val) {
expr = prop;
if (_status[expr]) {
otherStatus[expr] = val;
return _status[expr];
} else {
addStatusProperty(expr);
otherStatus[expr] = val;
return _status[expr];
}
};
var getStatusProperty = function (prop) {
expr = prop;
return _status[expr]
};
this.status = {
addProperty: addStatusProperty,
setProperty: setStatusProperty,
getProperty: getStatusProperty
};
var otherStatus = this.status;
};
var John = new Person({
name: "John"
});
John.status.setProperty('isOnfire', true);
John.status.setProperty('hasPinkShirt', true);
console.log(John, John.status.getProperty('isOnfire'), John.status.getProperty('hasPinkShirt'));