Reputation: 1
Check it out following code. The counter is declared as const. When you run it, it should not allow it to change in any situation!
function increment(counter) {
counter += 1;
}
function test() {
const counter = 1;
increment(counter);
}
When transpiled, it produces the following code. Which allows const counter to be incremented!
function increment(counter) {
counter += 1; // Counter is declared const, still it can be changed!
}
function test() {
var counter = 1;
increment(counter);
}
I'm just trying to understand, whether it is a problem with Babel transpilation or with JavaScript specification.
Edit:
I know that unlike ES6, the current version of JS does not support const
. My concern is, if I use transpiled JavaScript, I may encounter unknown const related bug. Should that be okay?
Upvotes: 0
Views: 2938
Reputation: 816462
Counter is declared const, still it can be changed!
There are two identifiers with name counter
in the transpiled code:
counter
inside increment
.counter
inside test
.They are completely independent!
Parameters are never "constant", they can always be assigned a new value. It has no impact on what you passed to the function, since all arguments are passed by value, i.e. increment
is passed the value of the variable counter
which is then assigned to the parameter counter
.
We can easily verify this by logging the value of the variable before and after the function call:
function increment(counter) {
counter += 1;
}
function test() {
var counter = 1;
console.log('value before', counter);
increment(counter);
console.log('value after', counter);
}
test();
I'm just trying to understand, whether it is a problem with Babel transpilation or with JavaScript specification
With neither. It works exactly has specified, no matter whether you are using var
or const
to declare counter
.
My concern is, if I use transpiled JavaScript, I may encounter unknown const related bug.
No, that won't be the case. What makes const
special? That you cannot assign a new value to it and that it is blocked scoped. So lets have a look what Babel does when you are violating these two constraints:
Input:
const foo = 21;
foo = 42;
Babel output:
Babel refuses to transpile the code with the error
SyntaxError: intput.js: "foo" is read-only
1 | const foo = 42;
> 2 | foo = 21;
| ^
3 |
Input:
{
const foo = 21;
}
console.log(foo); // trying to access const outside of block
Babel output:
"use strict";
{
var _foo = 21;
}
console.log(foo); // trying to access const outside of block
Babel renamed the block-scoped variable. foo
doesn't exist (as expected).
Upvotes: 8
Reputation: 5671
There are two things going on here:
value
of your variable and not the variable itself (as other answers have explained)const
to var
and still keeps the contract of not being re-assignable. I'll explain this part in my answer:The thing about babel and const, is that it only works via static analysis
The transpilation of working code converts const
into var
as that's all that exists in ES5.
const a = 0
const b = a + 1;
// becomes
var a = 0;
var b = a + 1;
The magic happens when babel finds you assigning a different value to your variable like so:
const a = 1;
a = a + 1;
// becomes
function _readOnlyError(name) { throw new Error("\"" + name + "\" is read-only"); }
var a = 1;
a = (_readOnlyError("a"), a + 1);
Because babel can tell it will throw an error by reading your code, it replaces the point where the error happens with an error.
So in effect for 99% of cases, const prevents re-assignment when converted to ES5.
The reason why your code wasn't transpiled to throw an error is because of part 1.
Upvotes: 1