Access default getter/setter for JavaScript object
可以使用
1 2 3 4 5 6 7 8 9 10 | Object.defineProperty(obj, 'foo', 'set': function(val) { if (useCustom) { doCustomProcessing(obj, 'foo', val); } else { obj['foo'] = val; } } ); |
不幸的是,这会导致堆栈溢出,因为
据我所知,一个属性要么有一个值(data属性),要么有getter/setter(accessor属性):它不能两者都有。使用闭包下的局部变量或其他属性作为定义了getter/setter的属性的基础存储。
例如,
1 2 3 4 5 6 7 8 9 10 11 12 13 | (function() { var value; Object.defineProperty(obj, 'foo', { set: function(val) { if (useCustom) { value = doCustomProcessing(obj, 'foo', val); } else { value = val; } }, get: function() { return value; } }); })(); |
在ES6中,可以使用代理对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | var myObject = {}; var myProxyObject = new Proxy(myObject, { set: function(ob, prop, value) { if (prop === 'counter' && value === 10) { // Some specialised behaviour ob.counter = 0; } else { // Default setter behaviour. ob[prop] = value; } // Return true otherwise you will get a TypeError in strict mode. return true; } }); >>> myProxyObject.counter = 5; >>> console.log(myProxyObject.counter); 5 >>> myProxyObject.counter = 10; >>> console.log(myProxyObject.counter); 0 |
我知道如何做到这一点的唯一方法是使变量非私有化,但有两个例子,第二个更简单:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | (function testInheritance(global, doc) { "use strict"; var MyFunc = Object.create({}, { _foo: { value:"Some Default Value", writable: true, enumerable: true }, foo: { get: function() { return this._foo; }, set: function(value) { this._foo = value; } } }), testFunc = Object.create(MyFunc); console.log(testFunc.foo); //"Some default value" testFunc.foo ="boo"; console.log(testFunc.foo); //"boo"; testFunc._foo ="Not a private variable anymore"; console.log(testFunc.foo); //"Not a private variable anymore" }(window, document)); (function testInheritanceTwo(global, doc) { "use strict"; var MyFunc = Object.create({}, { foo: { get: function() { if (!this._foo) { return"Some default value set by the getter."; } return this._foo; }, set: function(value) { this._foo = value; } } }), testFunc = Object.create(MyFunc); console.log(testFunc.foo); //"Some default value set by the getter." testFunc.foo ="Whomp"; console.log(testFunc.foo); //"Whomp"; testFunc._foo ="Not a private variable anymore, unfortunately."; console.log(testFunc.foo); //"Not a private variable anymore" }(window, document)); |
号
据我所知:
不能引用与set:function(value)中使用的名称相同的值,也不能以无限循环结束,在该循环中,设置值将调用set值并再次调用自身,依此类推。因此,你的问题。
如果试图将变量foo设为private,则setter不起作用。使用这种语法,您似乎可以隐藏变量,但不能真正将其设置为私有。