If `console.dir(x, {showHidden: true, });` prints `TestController {}`, does that mean x empty?

I wrote some code that keeps erroring saying click() does not exist on my testController object. To troubleshoot, I wrote this code:
const testController = new TestController();
console.dir(testController, {showHidden: true, }); // TestController {}
const testController = new TestController();
console.dir(testController, {showHidden: true, }); // TestController {}
Does TestController {} mean the object has no functions, properties, getters/setters, methods (or whatever word categorizes all of these things), or do I need to pass in different options to see everything on it?
45 Replies
ἔρως
ἔρως9mo ago
console: dir() method - Web APIs | MDN
The method console.dir() displays an interactive list of the properties of the specified JavaScript object. The output is presented as a hierarchical listing with disclosure triangles that let you see the contents of child objects.
ἔρως
ἔρως9mo ago
i dont see the 2nd parameter
Bawdy Ink Slinger
I'm writing typescript, and this is the generated js file for my class:
export class TestController {
click(selector
) {
const asyncClick = Promise.resolve(this).then((testController) => {
selector.$.trigger('click');
console.log(`asyncClick`, testController);
return testController;
});
return Object.assign(asyncClick, this);
}
expect(actual) {
return {};
}
}
export class TestController {
click(selector
) {
const asyncClick = Promise.resolve(this).then((testController) => {
selector.$.trigger('click');
console.log(`asyncClick`, testController);
return testController;
});
return Object.assign(asyncClick, this);
}
expect(actual) {
return {};
}
}
ἔρως
ἔρως9mo ago
so, no, there's no options or anything to send
Bawdy Ink Slinger
@ἔρως there is here: https://nodejs.org/api/console.html#consoledirobj-options I'm using node
ἔρως
ἔρως9mo ago
are you running the code in the browser or in node?
Bawdy Ink Slinger
node but i'm using jsdom that's why the code might appear otherwise
ἔρως
ἔρως9mo ago
Bawdy Ink Slinger
well, I have in the past but console.dir supposedly calls it anyway I guess I'll try it here too
ἔρως
ἔρως9mo ago
yeah, but seems that that has a lot more options maybe one of them will work for you
Bawdy Ink Slinger
const testController = new TestController();
console.log(inspect(testController, { showHidden: true, showProxy: true, getters: true})); // TestController {}
const testController = new TestController();
console.log(inspect(testController, { showHidden: true, showProxy: true, getters: true})); // TestController {}
Could I be missing something else or does this confirm it's an empty object?
ἔρως
ἔρως9mo ago
maxdepth as well set to null?
Bawdy Ink Slinger
you mean depth? same output
ἔρως
ἔρως9mo ago
yes then it's empty if you're in vscode, you can press f12 and see if there's anything in it
Bawdy Ink Slinger
you mean in debug mode or something?
ἔρως
ἔρως9mo ago
no
Bawdy Ink Slinger
oh no, nm
ἔρως
ἔρως9mo ago
just the editor put the prompt on the value, press f12 and it searches the definition
Bawdy Ink Slinger
Yeah, it takes me to my file:
import { Assertion } from './assertion';
import { Selector } from './selector';


export class TestController {
click(
this: TestController,
selector:
Selector
): TestControllerPromise {
const asyncClick = Promise.resolve(this).then<TestController>((testController) => {
selector.$.trigger('click');
console.log(`asyncClick`, testController);
return testController;
});
return Object.assign(asyncClick, this);
}

expect<A>(actual: A | Promise<A>): Assertion<A> {
return {} as Assertion<A>;
}
}

export interface TestControllerPromise<T = TestController>
extends TestController,
Promise<T> {}
import { Assertion } from './assertion';
import { Selector } from './selector';


export class TestController {
click(
this: TestController,
selector:
Selector
): TestControllerPromise {
const asyncClick = Promise.resolve(this).then<TestController>((testController) => {
selector.$.trigger('click');
console.log(`asyncClick`, testController);
return testController;
});
return Object.assign(asyncClick, this);
}

expect<A>(actual: A | Promise<A>): Assertion<A> {
return {} as Assertion<A>;
}
}

export interface TestControllerPromise<T = TestController>
extends TestController,
Promise<T> {}
I don't understand how it's possible to new TestController() and get an empty object back Am I making some obvious mistake?
ἔρως
ἔρως9mo ago
that's how objects work you get an object when you call new
Bawdy Ink Slinger
an empty one?
ἔρως
ἔρως9mo ago
no, it has 1 public method called expect
Bawdy Ink Slinger
why isn't click public? also, why doesn't it say expect is on the new TestController()?
ἔρως
ἔρως9mo ago
I KNOW! IT DOESN'T HAVE A CONSTRUCTOR wait, that doesn't make sense
Bawdy Ink Slinger
but if there is no defined constructor, doesn't it get a default, no-arg one?
ἔρως
ἔρως9mo ago
yeah that's why i said this try to use TestController.click directly? or pass TestController to console.dir?
Bawdy Ink Slinger
the typescript compiler says click doesn't exist. I can for it to run anyway if you want.
console.log(inspect(TestController, { showHidden: true, showProxy: true, getters: true, depth: null}));
/*
<ref *1> [class TestController] {
[length]: 0,
[name]: 'TestController',
[prototype]: {
[constructor]: [Circular *1],
[click]: [Function: click] { [length]: 1, [name]: 'click' },
[expect]: [Function: expect] { [length]: 1, [name]: 'expect' }
}
}
*/
console.log(inspect(TestController, { showHidden: true, showProxy: true, getters: true, depth: null}));
/*
<ref *1> [class TestController] {
[length]: 0,
[name]: 'TestController',
[prototype]: {
[constructor]: [Circular *1],
[click]: [Function: click] { [length]: 1, [name]: 'click' },
[expect]: [Function: expect] { [length]: 1, [name]: 'expect' }
}
}
*/
hm... So many questions, but is [constructor]: [Circular *1], normal?
ἔρως
ἔρως9mo ago
yes it's a circular reference it references TestController
Bawdy Ink Slinger
okay
ἔρως
ἔρως9mo ago
the length: 0 means it takes no arguments to create it
Bawdy Ink Slinger
I know how to read the rest of this output but I don't know what it tells me re: new TestController() returning an empty object
ἔρως
ἔρως9mo ago
I KNOW WHAT IT MAY BE, and if it is that, it's dumb as hell
Bawdy Ink Slinger
🙂
ἔρως
ἔρως9mo ago
the object doesn't have anything but the prototype does and the prototype is part of the constructor but what you have is no longer a constructor, but an instance to a class i may be absolutely wrong but it kinda makes sense
Bawdy Ink Slinger
I would've assumed inspect would have shown me I guess I'll create an empty constructor and see if that changes anything
ἔρως
ἔρως9mo ago
don't do that just try to do console.log(new TestController().click); and see what it says
Bawdy Ink Slinger
[Function: click]
ἔρως
ἔρως9mo ago
it works! i was right it didn't fetch the prototype 🤣 probably to avoid going down the prototype chain
Bawdy Ink Slinger
I don't see that as an option to show in inspect either?
ἔρως
ἔρως9mo ago
i didn't see anything either and it doesn't make sense either it should show 1 prototype, i think
Bawdy Ink Slinger
hm well here's what my code does now:
console.log(`inspecting TestController: `, inspect(TestController, { showHidden: true, showProxy: true, getters: true, depth: null}));
console.log(`inspecting new TestController: `, inspect(new TestController, { showHidden: true, showProxy: true, getters: true, depth: null}));
console.log(`inspecting new TestController(): `, inspect(new TestController(), { showHidden: true, showProxy: true, getters: true, depth: null}));
console.log(`inspecting new TestController().click: `, inspect(new TestController().click, { showHidden: true, showProxy: true, getters: true, depth: null}));
console.log(`inspecting new TestController().click(): `, inspect(new TestController().click, { showHidden: true, showProxy: true, getters: true, depth: null}));

/*
inspecting class name: <ref *1> [class TestController] {
[length]: 0,
[name]: 'TestController',
[prototype]: {
[constructor]: [Circular *1],
[click]: [Function: click] { [length]: 1, [name]: 'click' },
[expect]: [Function: expect] { [length]: 1, [name]: 'expect' }
}
}
inspecting new class name: TestController {}
inspecting new class name(): TestController {}
inspecting new class name().click: [Function: click] { [length]: 1, [name]: 'click' }
inspecting new class name().click(): [Function: click] { [length]: 1, [name]: 'click' }
*/
console.log(`inspecting TestController: `, inspect(TestController, { showHidden: true, showProxy: true, getters: true, depth: null}));
console.log(`inspecting new TestController: `, inspect(new TestController, { showHidden: true, showProxy: true, getters: true, depth: null}));
console.log(`inspecting new TestController(): `, inspect(new TestController(), { showHidden: true, showProxy: true, getters: true, depth: null}));
console.log(`inspecting new TestController().click: `, inspect(new TestController().click, { showHidden: true, showProxy: true, getters: true, depth: null}));
console.log(`inspecting new TestController().click(): `, inspect(new TestController().click, { showHidden: true, showProxy: true, getters: true, depth: null}));

/*
inspecting class name: <ref *1> [class TestController] {
[length]: 0,
[name]: 'TestController',
[prototype]: {
[constructor]: [Circular *1],
[click]: [Function: click] { [length]: 1, [name]: 'click' },
[expect]: [Function: expect] { [length]: 1, [name]: 'expect' }
}
}
inspecting new class name: TestController {}
inspecting new class name(): TestController {}
inspecting new class name().click: [Function: click] { [length]: 1, [name]: 'click' }
inspecting new class name().click(): [Function: click] { [length]: 1, [name]: 'click' }
*/
ἔρως
ἔρως9mo ago
yup, it doesn't go down the prototype chain that's bizarre but makes sense, as prototype chains can be extremely long
Bawdy Ink Slinger
thank you for the help 🙂
ἔρως
ἔρως9mo ago
you're welcome