๐ŸšงprintPrototypeChain()

๐Ÿšง under construction -> improve with TableMaker, make it a method.

JS โŸฉ types โŸฉ object โŸฉ prototype chain โŸฉ print

// importimport
const Iterator = require('./IteratorPrototype.js');
const { isPrimitive } = require('./isObject.js');
const { typeName } = require('./typeNames.js');
const { log } = console;

// โญ๏ธ prototype chain of value
function printPrototypeChainOf(value, name, {
    
    typeWidth=12,     // "type" column width
    noteWidth=23,     // "note" column width
    valueWidth=28,    // "value" column width
    
    prototypes=[],    // custom prototypes, format:
                      // {value: <value>, name: <name>}
}={}) {
    
    // if not an object, do nothing
    if (isPrimitive(value)) {
        log(`โ„น๏ธ value: ${value} is not an object.`);
        return;
    }

    // keep the original object for reference
    const original = value;

    // column widths
    const widths = {
        
        type: typeWidth,
        note: noteWidth,
        value: valueWidth,
        
        cols: 3,        // # of columns
        pad: 1,
            
            
        get total() {
            return this.type + this.note + this.value + (this.cols - 1) * this.pad
        }
    };

    // separator line
    const line = '-'.repeat(widths.total);
    const arrow = 'โ†’ ';
    
    // ๐Ÿ”ธ print row
    function print(type, note='', value='') {
        
        const items = [
            type.padEnd(widths.type, ' '),
            note.padEnd(widths.note, ' '),
            value,
        ];
        
        log(...items);
    }

    // table header
    log(`๐ŸŒŸ Prototype Chain of: `, name);
    log(line);
    print(`  type`, `prototype chain`, `value`);
    log(line);

    // ๐ŸŒŸ builtin prototypes
    const builtinPrototypes = [
        {value: Object.prototype, name: 'Object.prototype', hideValue: true},
        {value: Array.prototype, name: 'Array.prototype', hideValue: true},
        {value: Function.prototype, name: 'Function.prototype', hideValue: true},
        {value: Iterator.prototype, name: 'Iterator.prototype', hideValue: true},
    ];

    // ๐Ÿ”ธ known prototype ?
    function proto(obj) {

        prototypes = builtinPrototypes.concat(prototypes);
        type = 'โ€ข ' + typeName(obj);
        
        const result = {type: type, name: '(?)', value: obj }
        
        // test for prototypes
        for (const p of prototypes) {
            if (p.value === obj) {
                result.name = p.name;
                if (p.hideValue) result.value = '';
                break;
            }
        }

        result.name = arrow + result.name;
        return result;
    }

    // while value !== null, print it out
    while (value) {
        let p = proto(value);
        if (value === original) p.name = name;
        print(p.type, p.name, p.value);
        value = Object.getPrototypeOf(value);
    }

    // now, value === null
    print(`โ€ข Null`, arrow + 'โŒ', 'null');
    log(line+'\n');
    
}

// export
module.exports = {printPrototypeChainOf};

Last updated