💾ownPropertyFlags(obj)
JS ⟩ values ⟩ object ⟩ property ⟩ flag ⟩ ownPropertyFlags()
requires: isClass(), typeName()
// Dependencies:
// 🔸 ownPropertyFlags --> typeName --> isClass
"use strict";
const { log } = console;
// table of own property flags
// 🔸 require: typeName()
function ownPropertyFlags(obj, {
showFooter = true,
objectName = null,
} = {}) {
// padding between columns
const pad = ' ';
// convert descriptor (object) into string.
function descripterToString(prop, descriptor, propNameColWidth) {
const on = 'v', off = '.', icon = '🔸';
let result = icon + prop.padEnd(propNameColWidth + 2, ' ') + pad;
result += (descriptor.writable ? on : off) + ' ';
result += (descriptor.enumerable ? on : off) + ' ';
result += (descriptor.configurable ? on : off);
result += pad;
// check "value"
const value = descriptor.value;
switch (typeof value) {
case 'function':
result += `${value.name || '[no name]'} (${typeName(value)})`;
break;
default:
result += `${value}`;
}
return result
}
// get all (own) property descriptors
const descriptors = Object.getOwnPropertyDescriptors(obj);
// get all property names
const keys = Object.getOwnPropertyNames(descriptors);
// property name column width
const keyColumnWidth = Math.max(...keys.map(key => key.length));
// map all descriptors into array of strings
const lines = keys
.map(key => descripterToString(key, descriptors[key], keyColumnWidth));
// calculate table width
const tableWidth = Math.max(...lines.map(line => line.length));
// compose table content
const divider = '-'.repeat(tableWidth) + '\n';
const title = `${objectName || obj.name || '[no name]'} (${typeName(obj)})\n`;
const header = ' property'.padEnd(keyColumnWidth + 4, " ")
+ pad + 'w e c' + pad + 'value\n';
const footer = 'w: writable, e: enumerable, c: configurable\n';
let tableContent = title + divider + header + divider
+ lines.join('\n') + '\n'
+ divider;
if (showFooter) tableContent += footer;
log(tableContent);
return tableContent;
}
⭐️ property flags of a function
function F(name) {
this.name = name;
}
ownPropertyFlags(F);
// F (function)
// ---------------------------------------
// property w e c value
// ---------------------------------------
// 🔸length . . v 1
// 🔸name . . v F
// 🔸arguments . . . null
// 🔸caller . . . null
// 🔸prototype v . . [object Object]
// ---------------------------------------
// w: writable, e: enumerable, c: configurable
// ⭐ 注意: `F.prototype` 是 writable (可以被換掉)❗
// ⭐ every function has a default prototype
ownPropertyFlags(F.prototype, {
showFooter: false,
objectName: 'F.prototype'
});
// F.prototype (object)
// --------------------------------------
// property w e c value
// --------------------------------------
// 🔸constructor v . v F (function)
// --------------------------------------
⭐️ property flags of a class
class A {}
ownPropertyFlags(A, {showFooter: false});
// A (class)
// ---------------------------------------
// property w e c value
// ---------------------------------------
// 🔸length . . v 0
// 🔸name . . v A
// 🔸prototype . . . [object Object]
// ---------------------------------------
// ⭐ 注意:`A.prototype` 的 writable == false❗(不能被換掉❗)
ownPropertyFlags(A.prototype, {
showFooter: false,
objectName: 'A.prototype',
});
// A.prototype (object)
// -----------------------------------
// property w e c value
// -----------------------------------
// 🔸constructor v . v A (class)
// -----------------------------------
Last updated