npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

nv-facutil-has

v1.0.5

Published

A comprehensive utility for checking and inspecting object properties and prototype chains in JavaScript.

Readme

has - JavaScript Property Inspector

A comprehensive utility for checking and inspecting object properties and prototype chains in JavaScript.

Installation

const has = require('nv-facutil-has');

⚠️ Important Usage Note

The main function has() is designed for production use. All other utility functions are intended for CLI tools, testing frameworks, and debugging/inspection purposes only.

These inspection utilities provide deep introspection capabilities that are useful for:

  • Interactive REPL/CLI environments
  • Test assertions and debugging
  • Object structure analysis
  • Educational purposes

They are not recommended for production application logic due to performance considerations and complexity.


Main Function (Production Use)

has(object, key, only_own=false)

Checks if an object has a specific property.

Parameters:

  • object: The object to check
  • key: The property key (string or symbol)
  • only_own (default: false): If true, checks only own properties; if false, includes prototype chain

Returns: boolean

Examples:

const obj = { a: 1, b: 2 };

// Check with prototype chain
has(obj, 'a');           // true
has(obj, 'toString');    // true (inherited from Object.prototype)

// Check only own properties
has(obj, 'a', true);     // true
has(obj, 'toString', true); // false

// Safe with null/undefined
has(null, 'prop');       // false
has(undefined, 'prop');  // false

Inspection Utilities (CLI/Testing Only)

slow(object, key, dig=Infinity)

Searches for a property within a specified depth range in the prototype chain.

Parameters:

  • object: The object to search
  • key: The property key to find
  • dig (default: Infinity): Maximum depth to search
    • 0: Own properties only
    • n: Search up to n levels in prototype chain
    • Infinity: Search entire chain

Returns: boolean

Examples:

const grandparent = { a: 1 };
const parent = Object.create(grandparent);
parent.b = 2;
const child = Object.create(parent);
child.c = 3;

has.slow(child, 'c', 0);        // true (own property)
has.slow(child, 'b', 0);        // false (not own)
has.slow(child, 'b', 1);        // true (within 1 level)
has.slow(child, 'a', 2);        // true (within 2 levels)
has.slow(child, 'a', 1);        // false (need 2 levels)
has.slow(child, 'a', Infinity); // true (search all)

exact(object, key, depth=Infinity)

Checks if a property exists at an exact depth in the prototype chain.

Parameters:

  • object: The object to check
  • key: The property key
  • depth: Exact prototype chain depth
    • 0: Object's own property
    • n: Property at exactly n levels up
    • Infinity: Anywhere in chain

Returns: boolean

Examples:

const gp = { a: 1 };
const p = Object.create(gp);
p.b = 2;
const c = Object.create(p);
c.c = 3;

has.exact(c, 'c', 0);  // true (own property)
has.exact(c, 'b', 0);  // false (at level 1)
has.exact(c, 'b', 1);  // true (exactly at level 1)
has.exact(c, 'a', 1);  // false (at level 2, not 1)
has.exact(c, 'a', 2);  // true (exactly at level 2)

get_proto_chain(object)

Returns the complete prototype chain as an array.

Parameters:

  • object: The object to inspect

Returns: Array - Array of objects in the prototype chain

Examples:

const parent = { x: 1 };
const child = Object.create(parent);
child.y = 2;

const chain = has.get_proto_chain(child);
// [child, parent, Object.prototype]

console.log(chain.length);  // 3
console.log(chain[0] === child);   // true
console.log(chain[1] === parent);  // true

get_prop_descs(object, split_layer=false)

Retrieves property descriptors from the prototype chain.

Parameters:

  • object: The object to inspect
  • split_layer (default: false): Output format
    • false: Single object with all descriptors merged
    • true: Array of {object, descriptors} per layer

Returns: Object or Array

Examples:

const obj = { a: 1 };
Object.defineProperty(obj, 'b', {
    value: 2,
    writable: false,
    enumerable: true
});

// Merged format (default)
const descs = has.get_prop_descs(obj, false);
console.log(descs.a);
// { value: 1, writable: true, enumerable: true, configurable: true }

console.log(descs.b.writable);  // false

// Layer-by-layer format
const layers = has.get_prop_descs(obj, true);
layers.forEach((layer, i) => {
    console.log(`Layer ${i}:`, Object.keys(layer.descriptors));
});

get_all_keys(object, split_layer=false, enable_grouping=false)

Gets all property keys (including symbols and non-enumerable) from the prototype chain.

Parameters:

  • object: The object to inspect
  • split_layer (default: false): Separate by prototype layers
  • enable_grouping (default: false): Group by property characteristics

Returns: Array or Object

Property Signature Format (when enable_grouping=true):

  • k-__v-wec: string key, data property, writable+enumerable+configurable
  • k-g__-_ec: string key, getter only, enumerable+configurable
  • k-gs_-_e_: string key, getter+setter, enumerable only
  • y-__v-wec: symbol key, data property, writable+enumerable+configurable

Format: {keyType}-{propType}-{flags}

  • Key type: k (string) or y (symbol)
  • Property type: __v (data), g__ (getter), _s_ (setter), gs_ (both)
  • Flags: w (writable), e (enumerable), c (configurable), _ (absent)

Examples:

const obj = { a: 1 };
Object.defineProperty(obj, 'getter', {
    get: () => 'value',
    enumerable: true
});
const sym = Symbol('test');
obj[sym] = 'symbol value';

// Simple list
const keys = has.get_all_keys(obj);
console.log(keys);  // ['a', 'getter', Symbol(test)]

// Grouped by characteristics
const grouped = has.get_all_keys(obj, false, true);
console.log(grouped);
// {
//   'k-__v-wec': ['a'],
//   'k-g__-_ec': ['getter'],
//   'y-__v-wec': [Symbol(test)]
// }

// Split by layers
const parent = { x: 10 };
const child = Object.create(parent);
child.y = 20;

const layers = has.get_all_keys(child, true);
console.log(layers);
// [
//   ['y'],      // Layer 0: child's own
//   ['x']       // Layer 1: parent's own
// ]

nestify(object)

Converts a flat object into a nested prototype chain structure.

Parameters:

  • object: A flat object to convert

Returns: Object with properties distributed across prototype chain

How it works:

  • First property → deepest prototype
  • Middle properties → intermediate prototypes
  • Last property → object's own property

Examples:

const flat = { a: 100, b: 200, c: 300 };
const nested = has.nestify(flat);

// Resulting structure:
// nested (own): { c: 300 }
//   └─ prototype (empty layer)
//       └─ prototype: { b: 200 }
//           └─ prototype: { a: 100 }

console.log(nested.c);  // 300 (own property)
console.log(nested.b);  // 200 (from prototype)
console.log(nested.a);  // 100 (from deeper prototype)

console.log(Object.hasOwn(nested, 'c'));  // true
console.log(Object.hasOwn(nested, 'b'));  // false
console.log(Object.hasOwn(nested, 'a'));  // false

// Verify depths
has.exact(nested, 'c', 0);  // true
has.exact(nested, 'b', 2);  // true
has.exact(nested, 'a', 3);  // true

flatify(object)

Converts a nested prototype chain back into a flat object.

Parameters:

  • object: Object with prototype chain to flatten

Returns: Flat object with all properties merged

Examples:

const nested = has.nestify({ a: 1, b: 2, c: 3 });
const flat = has.flatify(nested);

console.log(flat);  // { c: 3, b: 2, a: 1 }

// All values preserved
console.log(flat.a === 1);  // true
console.log(flat.b === 2);  // true
console.log(flat.c === 3);  // true

// Round-trip preservation
const original = { x: 10, y: 20, z: 30 };
const restored = has.flatify(has.nestify(original));
// restored contains all original properties and values

Use Cases

Production Code

// Simple property existence check
if (has(config, 'database')) {
    // Use config.database
}

// Check own properties only
if (has(userInput, 'password', true)) {
    // Process password
}

Testing & Debugging

// In a test framework
describe('Object structure', () => {
    it('should have property at correct depth', () => {
        const obj = createComplexObject();
        assert(has.exact(obj, 'deepProp', 3));
    });
    
    it('should have all expected keys', () => {
        const keys = has.get_all_keys(obj, false, true);
        assert(keys['k-__v-wec'].includes('importantProp'));
    });
});

// In CLI inspection tool
function inspect(obj) {
    const chain = has.get_proto_chain(obj);
    console.log(`Prototype chain depth: ${chain.length}`);
    
    const descs = has.get_prop_descs(obj, true);
    descs.forEach((layer, i) => {
        console.log(`Level ${i}:`, Object.keys(layer.descriptors));
    });
}

Object Analysis

// Analyze object structure
function analyzeObject(obj) {
    const allKeys = has.get_all_keys(obj, false, true);
    
    console.log('Property distribution:');
    for (const [sig, keys] of Object.entries(allKeys)) {
        console.log(`${sig}: ${keys.length} properties`);
    }
    
    const layers = has.get_proto_chain(obj);
    console.log(`\nPrototype depth: ${layers.length}`);
}

Performance Considerations

Main function has():

  • Optimized for production use
  • O(1) for own properties
  • O(n) for prototype chain (where n = chain depth)

Inspection utilities:

  • May perform multiple traversals
  • Use reflection APIs (getOwnPropertyDescriptors, etc.)
  • Not optimized for high-frequency calls
  • Best suited for development/debugging scenarios

API Summary

| Function | Purpose | Production Use | |----------|---------|----------------| | has(o, key, only_own) | Check property existence | ✅ Yes | | slow(o, key, dig) | Search within depth range | ❌ No (CLI/Testing) | | exact(o, key, depth) | Check exact depth | ❌ No (CLI/Testing) | | get_proto_chain(o) | Get prototype chain | ❌ No (CLI/Testing) | | get_prop_descs(o, split) | Get property descriptors | ❌ No (CLI/Testing) | | get_all_keys(o, split, group) | Get all keys with details | ❌ No (CLI/Testing) | | nestify(o) | Flatten to chain | ❌ No (CLI/Testing) | | flatify(o) | Chain to flat | ❌ No (CLI/Testing) |


License

MIT