1. Reflect.get and Reflect.set Mirror Property Access
Code:
const input = document.querySelector('#basicInput');
const output = document.querySelector('#basicOutput');
const directButton = document.querySelector('#basicDirect');
const reflectButton = document.querySelector('#basicReflect');
const readButton = document.querySelector('#basicRead');
directButton.addEventListener('click', () => {
input.value = 'direct assignment';
output.textContent = "input.value = 'direct assignment'";
});
reflectButton.addEventListener('click', () => {
Reflect.set(input, 'value', 'Reflect.set value');
output.textContent = "Reflect.set(input, 'value', 'Reflect.set value')";
});
readButton.addEventListener('click', () => {
output.textContent =
`Reflect.get(input, 'value') -> ${Reflect.get(input, 'value')}`;
});
Result:
2. Reflect.defineProperty Can Redefine DOM Behavior
Code:
const input = document.querySelector('#descriptorInput');
const output = document.querySelector('#descriptorOutput');
const setButton = document.querySelector('#descriptorSet');
const clearButton = document.querySelector('#descriptorClear');
const props = Reflect.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value');
Reflect.defineProperty(input, 'value', {
...props,
set(value) {
let oldValue = this.value;
props.set.call(this, value);
if (oldValue !== value) {
this.dispatchEvent(new CustomEvent('change'));
}
}
});
input.addEventListener('change', () => {
output.append('It changed~ ');
});
setButton.addEventListener('click', () => {
input.value = 'zhangxinxu';
});
clearButton.addEventListener('click', () => {
input.value = '';
output.textContent = '';
});
Result:
3. Reflect.set Returns Whether Assignment Worked
Code:
const input = document.querySelector('#readonlyTypeInput');
const output = document.querySelector('#readonlyTypeOutput');
const runButton = document.querySelector('#readonlyTypeRun');
Object.defineProperty(input, 'type', {
configurable: true,
get() {
return this.getAttribute('type') || 'text';
}
});
runButton.addEventListener('click', () => {
const assignmentResult = (input.type = 'number');
const reflectResult = Reflect.set(input, 'type', 'number');
output.textContent = [
`input.type = 'number' -> ${assignmentResult}`,
`Reflect.set(input, 'type', 'number') -> ${reflectResult}`,
`Actual input.type -> ${input.type}`
].join('\n');
});
Result:
4. Reflect.set Avoids Strict-Mode Interruption
Code:
const direct = document.querySelector('#frozenDirect');
const reflect = document.querySelector('#frozenReflect');
const output = document.querySelector('#frozenOutput');
direct.addEventListener('click', () => {
output.textContent = '';
try {
(function () {
'use strict';
var frozen = { 1: 81 };
Object.freeze(frozen);
frozen[1] = 'zhangxinxu';
output.textContent += 'no log';
})();
} catch (error) {
output.textContent = `${error.name}: ${error.message}`;
}
});
reflect.addEventListener('click', () => {
output.textContent = '';
(function () {
'use strict';
var frozen = { 1: 81 };
Object.freeze(frozen);
var ok = Reflect.set(frozen, '1', 'zhangxinxu');
output.textContent += `Reflect.set returned ${ok}\n`;
output.textContent += 'no log';
})();
});
Result:
5. Proxy Handlers Pair Naturally with Reflect
Code:
const input = document.querySelector('#proxyInput');
const output = document.querySelector('#proxyOutput');
const setButton = document.querySelector('#proxySet');
const readButton = document.querySelector('#proxyRead');
const clearButton = document.querySelector('#proxyClear');
const xyInput = new Proxy(input, {
set(target, prop, value) {
if (prop == 'value') {
target.dispatchEvent(new CustomEvent('change'));
}
return Reflect.set(target, prop, value);
},
get(target, prop) {
return Reflect.get(target, prop);
}
});
input.addEventListener('change', () => {
output.append('It changed~ ');
});
setButton.addEventListener('click', () => {
xyInput.value = 'zhangxinxu';
});
readButton.addEventListener('click', () => {
output.append(`value: ${xyInput.value} `);
});
clearButton.addEventListener('click', () => {
input.value = '';
output.textContent = '';
});
Result:
6. receiver Keeps Inherited Getters Honest
Code:
const output = document.querySelector('#receiverOutput');
const targetName = document.querySelector('#receiverTargetName');
const childName = document.querySelector('#receiverChildName');
const run = document.querySelector('#receiverRun');
run.addEventListener('click', () => {
let miaoMiao = {
_name: targetName.value || 'vaccine',
get name() {
return this._name;
}
};
let noReceiverProxy = new Proxy(miaoMiao, {
get(target, prop, receiver) {
return target[prop];
}
});
let reflectProxy = new Proxy(miaoMiao, {
get(target, prop, receiver) {
return Reflect.get(target, prop, receiver);
}
});
let noReceiverChild = {
__proto__: noReceiverProxy,
_name: childName.value || 'Sinovac vaccine'
};
let reflectChild = {
__proto__: reflectProxy,
_name: childName.value || 'Sinovac vaccine'
};
output.textContent = [
`target[prop] result: ${noReceiverChild.name}`,
`Reflect.get(..., receiver) result: ${reflectChild.name}`
].join('\n');
});
Result:
7. Reflect Methods Mirror Existing APIs and Operators
Code:
const methods = [
['Reflect.apply(target, thisArgument, argumentsList)', 'Function.prototype.apply()'],
['Reflect.construct(target, argumentsList[, newTarget])', 'new target(...args)'],
['Reflect.defineProperty(target, prop, attributes)', 'Object.defineProperty()'],
['Reflect.deleteProperty(target, prop)', 'delete target[name]'],
['Reflect.get(target, prop[, receiver])', 'target[name]'],
['Reflect.getOwnPropertyDescriptor(target, prop)', 'Object.getOwnPropertyDescriptor()'],
['Reflect.getPrototypeOf(target)', 'Object.getPrototypeOf()'],
['Reflect.has(target, prop)', 'in operator'],
['Reflect.isExtensible(target)', 'Object.isExtensible()'],
['Reflect.ownKeys(target)', 'Object.keys()'],
['Reflect.preventExtensions(target)', 'Object.preventExtensions()'],
['Reflect.set(target, prop, value[, receiver])', 'target[prop] = value'],
['Reflect.setPrototypeOf(target, prototype)', 'Object.setPrototypeOf()']
];
const filter = document.querySelector('#tableFilter');
const body = document.querySelector('#tableBody');
function renderReflectTable() {
const query = filter.value.toLowerCase();
body.innerHTML = '';
methods
.filter(([reflect, similar]) => `${reflect} ${similar}`.toLowerCase().includes(query))
.forEach(([reflect, similar]) => {
const row = document.createElement('tr');
const reflectCell = document.createElement('td');
const similarCell = document.createElement('td');
reflectCell.textContent = reflect;
similarCell.textContent = similar;
row.append(reflectCell, similarCell);
body.append(row);
});
}
filter.addEventListener('input', renderReflectTable);
renderReflectTable();
Result:
| Reflect Method | Similar To |
|---|