2017-10-11 68 views
1

以下代碼包含代理get陷阱對象的__proto__。當根據js邏輯獲取某個屬性時,只有當對象本身不包含相應的屬性時纔會調用陷阱。所以在賦值之後,屬性出現在對象中,並且不調用陷阱。它完全按照我的意願工作。指定以上代理的屬性

var x = Object.create(new Proxy({}, { 
 
    get(obj, key) { 
 
    if (typeof key !== 'symbol') { 
 
     console.log('Reading a nonexisting property: ' + key); 
 
    } 
 
    } 
 
})); 
 

 
var temp; 
 
console.log(1, Object.prototype.hasOwnProperty.call(x, 'a')); 
 

 
temp = x.a; 
 
console.log(2, Object.prototype.hasOwnProperty.call(x, 'a'), temp); 
 

 
temp = x.a; 
 
console.log(3, Object.prototype.hasOwnProperty.call(x, 'a'), temp); 
 

 
x.a = 12; 
 
console.log(4, Object.prototype.hasOwnProperty.call(x, 'a')); 
 

 
temp = x.a; 
 
console.log(5, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
.as-console-wrapper.as-console-wrapper { max-height: 100vh }

現在我加入了set陷阱:

var x = Object.create(new Proxy({}, { 
 
    get(obj, key) { 
 
    if (typeof key !== 'symbol') { 
 
     console.log('Reading a nonexisting property: ' + key); 
 
    } 
 
    }, 
 
    set(obj, key, val, receiver) { 
 
    console.log('Assigning a property: ' + key); 
 
    Reflect.set(obj, key, val); // Inside of proxy, not outside 
 
    //Reflect.set(receiver, key, val); // Infinite recursion 
 
    return true; 
 
    } 
 
})); 
 

 
var temp; 
 
console.log(1, Object.prototype.hasOwnProperty.call(x, 'a')); 
 

 
temp = x.a; 
 
console.log(2, Object.prototype.hasOwnProperty.call(x, 'a'), temp); 
 

 
temp = x.a; 
 
console.log(3, Object.prototype.hasOwnProperty.call(x, 'a'), temp); 
 

 
x.a = 12; 
 
console.log(4, Object.prototype.hasOwnProperty.call(x, 'a')); 
 

 
temp = x.a; 
 
console.log(5, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
.as-console-wrapper.as-console-wrapper { max-height: 100vh }

的問題是,我不能直接寫一個屬性對象。該物業要麼被寫入的物品而不是物品包裝代理或無限遞歸set陷阱發生。

所以我想要得到與第一個片段相同的輸出,但用新行Assigning a property: a

PS:Same qusetion in Russian.

回答

2

要真正創建一個屬性,你將不得不使用Object.defineProperty(或Reflect.defineProperty,如果你喜歡)。只需通過賦值或Reflect.set來設置屬性的確會遍歷原型鏈,所以當您在原型設置器(或代理陷阱)中對某個對象執行此操作時,您總是可以獲得遞歸。

您可以使用

new Proxy({}, { 
    get(target, key) { 
    if (typeof key !== 'symbol') { 
     console.log('Reading a nonexisting property: ' + key); 
    } 
    }, 
    set(target, key, val, receiver) { 
    console.log('Assigning a property: ' + key); 
    return Reflect.defineProperty(receiver, key, { 
     value: val, 
     writable: true, 
     enumerable: true, 
     configurable: true 
    }); 
    } 
}); 

全碼:

var x = Object.create(new Proxy({}, { 
 
    get(obj, key) { 
 
    if (typeof key !== 'symbol') { 
 
     console.log('Reading a nonexisting property: ' + key); 
 
    } 
 
    }, 
 
    set(obj, key, val, receiver) { 
 
    console.log('Assigning a nonexisting property: ' + key); 
 

 
    return Reflect.defineProperty(receiver, key, { 
 
     value: val, 
 
     writable: true, 
 
     enumerable: true, 
 
     configurable: true 
 
    }); 
 
    } 
 
})); 
 

 
var temp; 
 
console.log(1, Object.prototype.hasOwnProperty.call(x, 'a')); 
 

 
temp = x.a; // get trap 
 
console.log(2, Object.prototype.hasOwnProperty.call(x, 'a'), temp); 
 

 
temp = x.a; // get trap 
 
console.log(3, Object.prototype.hasOwnProperty.call(x, 'a'), temp); 
 

 
x.a = 12; // set trap creates a property and sets it 
 
console.log(4, Object.prototype.hasOwnProperty.call(x, 'a')); 
 

 
temp = x.a; // direct read - no traps 
 
console.log(5, Object.prototype.hasOwnProperty.call(x, 'a'), temp); 
 

 
x.a = 42; // direct write - no traps 
 
console.log(6, Object.prototype.hasOwnProperty.call(x, 'a')); 
 

 
temp = x.a; // direct read - no traps 
 
console.log(7, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
.as-console-wrapper.as-console-wrapper { max-height: 100vh }

+0

偉大的答案!謝謝! 我已經添加了可運行示例的代碼片段,希望您沒有任何異議:) – Qwertiy