const function parameters

Note: this is a cross-post from https://discourse.wicg.io/t/js-const-function-parameters/1927

let creates a mutable binding, and const creates an immutable binding. However function parameters are always implicity mutable, i.e.:

function foo(param) // 'param' is implicitly mutable
{
    console.log("param = " + param);
    param = 5;  // this is allowed
    console.log("param = " + param);
};

Why not allow const in function parameters?

function foo(const param) // 'param' is immutable
{
    console.log("param = " + param);
    param = 5;  // throws, cannot modify const parameter
    console.log("param = " + param);
};

In the second example using param would be treated the same as if it were defined as a local variable with const instead of let .

This would provide the same benefits as const for function parameters, i.e. readability, indicating intent, avoiding accidental modification of parameters, etc.

This would be extended to default parameters, e.g.

function foo(const param = 0)
{
    // ...
};

Perhaps for consistency let should then also be allowed to explicity indicate a mutable parameter? e.g.

function foo(let param)
{
    // ...
};
2 Likes

Do you foresee allowing function (var formalName) {...} as well?

Would you like this to extend to catch parameters?

Re allowing (let formalpattern) for consistency:

IIRC, let is allowed as a function parameter name since it was never a FutureReservedWord the way const was. (let => let)(typeof let)

But let let is not allowed. So we'd need to decide which is worse. Allow

let let = (let let) => let

or allow (let let) => ... as a formal parameter but not allow a declaration like let let;

1 Like

FWIW, this is something that I wouldn't mind having. @mikesamuel has a good point regarding catch blocks, but the rest of the comment seems absurd to me, as both var and let in that position wouldn't change the semantics.

OTOH, being able to guarantee that the binding of the parameters won't change sounds like a good ergonomic addition.

Why not just write a linter plugin for this?

Good point. Not mutating the arguments is usually the sane default, having this would result in codebases littered with const.

…or use an existing one, like ESLint's no-param-reassign rule?

3 Likes

This is about ensuring the language itself provides guarantees. Linters don't do that. That's why const for variable declarations is part of the language itself, rather than a linter check, and this proposal is an extension of that.

It's a good point about backwards compatibility and consistency. It seems like the easiest option for compatibility is to only support const for function parameters and not let or var. But this does make it kind of inconsistent with variable declarations. On the other hand, you could argue since function parameters never needed let or var and have always defaulted to mutable, there's no need for them to be supported in function parameters. Since only const would actually change anything about the parameter, perhaps it is actually fitting that only the const keyword is supported in parameters.

This is about ensuring the language itself provides guarantees. Linters don't do that. That's why const for variable declarations is part of the language itself, rather than a linter check, and this proposal is an extension of that.

Engines have optimizations for "effectively-constant" variables, with Edge being the first and V8 following suit not long after. If it's statically analyzable, engines can generally infer it - it's the runtime values they struggle with the most.