在对象上设置属性时调用函数

时间:2012-07-18 23:54:30

标签: javascript node.js

我真的不知道如何解释这个,但我会告诉你代码并告诉你我想要实现的目标。

假设我做了一个快速的对象:

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

非常感谢,祝你有愉快的一天!

5 个答案:

答案 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.";