class Foo { constructor() { this.x = 1; this.self = this; } m() { return this.x; }; getSelf() { return this } test() { const Foo = this; const o = { Foo: Foo }; const fn = function () { return o; }; expect((Foo?.["m"])()).toEqual(1); expect((Foo?.["m"])().toString).toEqual(1..toString); expect((Foo?.["m"])().toString()).toEqual('1'); expect(((Foo?.["m"]))()).toEqual(1); expect(((Foo?.["m"]))().toString).toEqual(1..toString); expect(((Foo?.["m"]))().toString()).toEqual('1'); expect((o?.Foo.m)()).toEqual(1); expect((o?.Foo.m)().toString).toEqual(1..toString); expect((o?.Foo.m)().toString()).toEqual('1'); expect((((o.Foo?.self.getSelf)())?.m)()).toEqual(1); expect((((o.Foo.self?.getSelf)())?.m)()).toEqual(1); expect((((fn()?.Foo?.self.getSelf)())?.m)()).toEqual(1); expect((((fn?.().Foo.self?.getSelf)())?.m)()).toEqual(1); } testNull() { const o = null; expect(() => { (o?.Foo.m)() }).toThrow(); expect(() => { (o?.Foo.m)().toString }).toThrow(); expect(() => { (o?.Foo.m)().toString() }).toThrow(); expect(() => { (((o.Foo?.self.getSelf)())?.m)() }).toThrow(); expect(() => { (((o.Foo.self?.getSelf)())?.m)() }).toThrow(); expect(() => (((fn()?.Foo?.self.getSelf)())?.m)()).toThrow(); expect(() => (((fn?.().Foo.self?.getSelf)())?.m)()).toThrow(); } } (new Foo).test(); (new Foo).testNull();