2

I am writing some ES/JS tooling. In DevTools I can see lots of classes, e.g. ArrayBuffer. Yet when I try to extract such names from window global context, I can't see them. This snippet gives similar results in Chrome, FireFox and Opera.

MWE on JSFiddle

console.log('typeof window.ArrayBuffer:', 
        typeof window.ArrayBuffer);
console.log("window.hasOwnProperty('ArrayBuffer'):", 
        window.hasOwnProperty('ArrayBuffer'));

let c = 0;
for (let n in window) {
    // console.log(n);
    if (n == 'ArrayBuffer') {
        console.log('FOUND: ArrayBuffer');
    }
    c++;
}
console.log(c + ' attributes checked')

If I uncomment the // console.log(n); line, I can see the names of the attributes, but none of the classes.

How do I access those class (API) names?

CyberFonic
  • 3,957
  • 1
  • 21
  • 21

2 Answers2

4

It's matter of Object's Enumerable properties.

for in (as well as Object.keys/values/entries) does not account for non enumerable properties:

window.hasOwnProperty('ArrayBuffer');       // true
window.propertyIsEnumerable('ArrayBuffer'); // false
// Therefore will not show up in for-in loop

To create a non-enumerable object property, an example is by using Object.defineProperty

const obj = {a: 1, b: 2, c: 3};
for (const prop in obj) console.log(obj[prop]); // 1 2 3

Object.defineProperty(obj, "d", {
  value: 4,
  // enumerable: false,      // defaults to false!!
  // set to true to make it enumerable
});

for (const prop in obj) console.log(obj[prop]); //  1 2 3 (no 4 visible)

// Same goes for iterating using Object.keys and Object.values:
console.log(...Object.values(obj)) // 1 2 3 (no 4 visible)

To get all the properties of an Object you might use instead Object.getOwnPropertyNames:

const props = Object.getOwnPropertyNames(window);

console.log(props.includes('ArrayBuffer'));                    // true
console.log(props.some(pr => pr === 'ArrayBuffer'));           // true
console.log(props.findIndex(pr => pr === 'ArrayBuffer') > -1); // true

console.log(props.length);                   // 963
console.log(Reflect.ownKeys(window).length); // 963

// See them all:
console.log(props);

// Loop them all:
// props.forEach(pr => console.log(pr));

Keep in mind that for...in loops only enumerable properties - with the exception of Symbols.

To get an Array ot the Object's own-property keys with Symbols use Reflect.ownKeys

The Reflect.ownKeys method returns an array of the target object's own property keys. Its return value is equivalent to Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))

Additional read:

Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
  • I would like to see all the properties of window, e,g, Animation, Audio. ArrayBuffer is just one example. BTW: window.propertyIsEnumerable('window'); // true. – CyberFonic Feb 20 '21 at 02:47
  • @CyberFonic see the last example `props.forEach(pr => console.log(pr));` (not appropriate for Stack Snippets since there's a load of properties that do not fit into the Stack Snippet console) – Roko C. Buljan Feb 20 '21 at 02:59
  • @CyberFonic regarding your question about `"window" // true`... since it's enumerable **will shop up** using *for...in*: `for(p in window) {if(p=="window") console.log(p);} // "window"` -- therefore it's enumerable: `window.propertyIsEnumerable('window'); // true`. Also, if it might interest you: for the case `window.window.window.window` etc... returning Window - refer to: https://developer.mozilla.org/en-US/docs/Web/API/Window/window – Roko C. Buljan Feb 20 '21 at 03:29
1

Use Object.getOwnPropertyNames() to get all properties (including non-enumerable properties except for those which use Symbol). Then loop through them to find the class name:

Object.getOwnPropertyNames(window).forEach((n) => {
    if (n === 'ArrayBuffer') {
        console.log('FOUND: ArrayBuffer');
    }
})
hoangdv
  • 15,138
  • 4
  • 27
  • 48
  • Went from 214 attributes found to 958. Checked by printing all attributes found and it matches what DevTools shows. – CyberFonic Feb 20 '21 at 03:53