I want to create function that will return all properties of an object:
This is my initial code:
function dir(obj) {
if (obj === null || obj === Object.prototype) {
return [];
}
var names = Object.getOwnPropertyNames(obj);
return names.concat(dir(Object.getPrototypeOf(obj)));
}
and I have ES6 class where I want to hide some properties:
class Lexer {
constructor(input, { whitespace = false } = {}) {
this.__input__ = input.replace(/\r/g, '');
var internals = {};
[
'_i', '_whitespace', '_col', '_newline', '_line',
'_state', '_next', '_token', '_prev_char'
].forEach(name => {
Object.defineProperty(this, name, {
configurable: false,
enumerable: false,
get() {
return internals[name];
},
set(value) {
internals[name] = value;
}
});
});
this._whitespace = whitespace;
this._i = this._line = this._col = this._newline = 0;
this._state = this._next = this._token = null;
this._prev_char = '';
}
token() {
}
...
}
The problem I have is that Object.getOwnPropertyNames
return enumerable properties and Object.key
don't return ES6 class methods. So I if Use the first function I get hidden props and if I use second I only get __input__
.
Is there a way to detect if something is hidden property and not ES6 class method? I don't want to detect if something is a function because I want something more generic there can be not enumerable properties that are functions.
I've also found that for ES5 constructor function there is constructor property that is also not enumerable and behave like ES6 method (in case of my Lexer class it work the same token method).
NOTE: this is not Y/X problem I want to create dir
function for my Scheme interpreter that will work like similar function in Python, it should work with ES5 function constructor objects and ES6 class objects.
I've tried this:
function dir(obj, proto) {
if (obj === null || obj === Object.prototype) {
return [];
}
var names = Object.getOwnPropertyNames(obj);
if (!proto) {
names = names.filter(name => {
var d = Object.getOwnPropertyDescriptor(obj, name);
return d.configurable && d.enumerable;
});
}
return names.concat(dir(Object.getPrototypeOf(obj), true));
}
but I don't know if this is the best way, since the user may want to create property descriptor of prototype (i'm not sure if this is something that may happen). I want 100% working solution and not work around. Do you know any method to make it work?
EDIT:
Even that I have working solution for my case, I'm wondering if ES6 properties in fact are indistinguishable from not enunumerable properties.
Especially if you can detect if foo
is different then bar
:
class Test {
constructor() {
Object.defineProperty(this, 'foo', {
enumerable: false,
configurable: false,
value: function() { alert('foo') }
});
}
bar() {
alert('bar');
}
}
Is the only difference is that bar is on prototype object and there are no other way to detect the difference?