In theory, using the authorization code flow (or the hybrid flow) with a JS/mobile/desktop application is definitely possible, and you don't even need to store client credentials for that (you could, of course, but extracting them is so easy that it would be pointless).
Contrary to popular belief, client authentication is not required for "public" applications (i.e apps that cannot safely store their credentials, which includes JS apps) when using the authorization code flow:
If the client type is confidential or the client was issued client
credentials (or assigned other authentication requirements), the
client MUST authenticate with the authorization server as described
in Section 3.2.1.
https://www.rfc-editor.org/rfc/rfc6749#section-4.1.3
f the Client is a Confidential Client, then it MUST authenticate to the Token Endpoint using the authentication method registered for its client_id, as described in Section 9.
http://openid.net/specs/openid-connect-core-1_0.html#TokenRequest
In practice, I'm pretty sure most authorization/authentication servers will enforce client authentication when using the authorization code flow and will instead recommend using the implicit flow for public apps.
If your authorization server supports this scenario, using the authorization code flow in your JS app should be easy if you use response_mode=query
(or better: response_mode=fragment
as suggested by @Hans), since you can use your JS main page as the redirect_uri
and use some JS to extract the authorization code from the query string or from the fragment.