我真的不知道如何解释这个,但我会告诉你代码并告诉你我想要实现的目标。
假设我做了一个快速的对象:
var test = {};
然后我为它设置了一个属性:(我坚持语法,它不能使用任何函数作为setter)
test.hello = 'world';
很简单,嗯?现在我想向该对象添加一个函数,每次设置一个新属性时都会调用该函数。像这样:
var test = {
newPropertyHasBeenSet: function(name){
console.log(name + 'has been set.');
}
};
test.hello = 'world';
// Now newPropertyHasBeenSet gets called with 'hello' as an argument.
// hello has been set.
我不知道是否可能,但那会非常棒。任何人都知道如何实现这一目标?
编辑:我也希望能够为属性获取做同样的事情(因此test.hello
会调用get('hello')
)。
EDIT2:这是针对使用node.js的服务器端javascript 。
非常感谢,祝你有愉快的一天!
答案 0 :(得分:7)
在chrome中尝试此示例(如之前的评论中所述,它使用ES6 Proxy):
var p = Proxy.create({
get: function(proxy, name) {
console.log('read request to ' + name + ' property');
if (name=="test_test")
return 1234;
else
return "Meh";
},
set: function(proxy, name, value) {
console.log('write request to ' + name + ' property with ' + value + ' value');
}
});
console.log(p.test_test);
console.log(p.test)
p.qqq = "test";
结果:
read request to test_test property
1234
read request to test property
Meh
write request to qqq property with test value
答案 1 :(得分:2)
var test = {};
Object.defineProperty(test, "hello", {
get : function () {
return this._hello;
},
set : function (val) {
alert(val);
this._hello = val;
}
});
test.hello = "world";
这样的事情。但它不适用于旧浏览器。
您可以在此处找到更多选项:http://robertnyman.com/javascript/javascript-getters-setters.html
答案 2 :(得分:2)
如果您真的坚持使用test.hello = "world"
语法来检测现有属性的更改,那么您必须等待几年才能使Object.watch
成为下一个EcmaScript标准。
幸运的是,您可以使用Object.defineProperty
在EcmaScript 5中执行相同的操作。你可以这样称呼的Eli Grey made a nice Object.watch
polyfill:
var test = {};
test.watch("hello", function(propertyName, oldValue, newValue) {
console.log(propertyName + " has been set to " + newValue);
});
test.hello = "world"; // triggers the watch handler
您可以修改他的代码以在getter
内触发不同的处理程序,这样您就可以检测属性访问。
不幸的是,browser support is limited to modern browsers包括Internet Explorer 9,Firefox 4,Chrome,Opera 12和Safari 5.
如果您想在设置新属性时触发处理程序,则会遇到更多麻烦。您可以做的最好的事情是将对象包裹在proxy内并放置set
陷阱。然后,您可以通过测试this.getOwnPropertyDescriptor(name)
是否返回'truthy'值来检测该属性是否已存在。 Proxy API非常具有实验性,只有少数浏览器提供了一个原型实现。您可能需要等待一段时间才能获得具有良好浏览器支持的完整API。
答案 3 :(得分:0)
您需要一个提供键值观察和绑定的库。
ember-metal is one such library.
基本上你创建了对象,你可以在这些对象的属性上注册观察者。
var obj = Em.Object.create({
val: null
valDidChange:function(){...}.observes('val')
});
只要val
属性发生变化,valDidChange就会触发,所以
obj.set('val', 'newValue');
将导致观察者开火。
答案 4 :(得分:0)
这样的事情怎么样? Here's a jsfiddle.
var objectManager = function(obj, setCallback){
this.obj = obj;
this.setCallback = setCallback;
};
objectManager.prototype.setProperty = function(prop, value){
this.obj[prop] = value;
this.setCallback(prop);
};
objectManager.prototype.getObj = function(){
return this.obj;
};
// USAGE:
var testMgr = new objectManager({}, function(prop){
console.log(name + ' has been set.');
});
testMgr.setProperty("hello", "world"); //should log "hello has been set.";