Object.defineProperty
Promise
仅当目标浏览器不支持 Promise 时,才删除 Promise 并保留回调
重要的:
1)注意使用promise的异步行为。
2) Object.defineProperty 不触发回调,只赋值运算符'='
Object.onPropertySet = function onPropertySet(obj, prop, ...callback_or_once){
let callback, once;
for(let arg of callback_or_once){
switch(typeof arg){
case "function": callback = arg; break;
case "boolean": once = arg; break;
}
}
let inner_value = obj[prop];
let p = new Promise(resolve => Object.defineProperty(obj, prop, {
configurable: true,
// enumerable: true,
get(){ return inner_value; },
set(v){
inner_value = v;
if(once){
Object.defineProperty(obj, prop, {
configurable: true,
// enumerable: true,
value: v,
writable: true,
});
}
(callback || resolve)(v);
}
}));
if(!callback) return p;
};
// usage
let a = {};
function sayHiValue(v){ console.log(`Hi "${v}"`); return v; }
// do
Object.onPropertySet(a, "b", sayHiValue);
a.b = 2; // Hi "2"
a.b = 5; // Hi "5"
// or
Object.onPropertySet(a, "c", true).then(sayHiValue).then(v => {
console.log(a.c); // 4 // because a.c is set immediatly after a.c = 3
console.log(v); // 3 // very important: v != a.c if a.c is reassigned immediatly
a.c = 2; // property "c" of object "a" is re-assignable by '=' operator
console.log(a.c === 2); // true
});
a.c = 3; // Hi "3"
a.c = 4; // (Nothing)