最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why does Babel not properly handle const? - Stack Overflow

programmeradmin5浏览0评论

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?

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?

Share Improve this question edited Feb 5, 2018 at 5:58 Aamir Maniar asked Feb 5, 2018 at 2:27 Aamir ManiarAamir Maniar 11 silver badge2 bronze badges 4
  • 3 counter isn't incremented. It's passed by value -- not reference -- to the increment function. Examine const counter's value after the increment function has been called and you'll see that it hasn't changed. I think we can both agree that, eg, literal 1 is constant. As a thought experiment, what happens when you call increment(1)? Do all the 1s in your source code turn into 2s? – Kelvin Sherlock Commented Feb 5, 2018 at 3:08
  • Your code example won't even increment the original counter variable in actual ES6 because of the pass by value, not reference (which means a non-const copy of counter is what is passed to the function. You can't make function parameters const either. So, this has nothing to do with Babel. This is how Javascript works. – jfriend00 Commented Feb 5, 2018 at 4:33
  • The title of your question is a wrong assertion about how passing arguments work in Javascript. You appear to be thinking that passing a const variable as a function argument will "retain" the const for that function parameter. Javascript does not do that. Function parameters are copies or pointers. They aren't the original const variable. – jfriend00 Commented Feb 5, 2018 at 5:11
  • All parameters are always passed by value in Javascript. For primitives (Number, String, Boolean) this means the value is copied. So whatever you do with the (copied) value inside the function will have no effect on the value that the caller passed in. When you pass an object or an array to a function, the parameter is still passed by value, but those values are actually references (like, but not quitte the same as, pointers), meaning they just contain a reference to the actual object, which lives on the heap. – Stijn de Witt Commented Jan 14, 2019 at 8:07
Add a ment  | 

2 Answers 2

Reset to default 8

Counter is declared const, still it can be changed!

There are two identifiers with name counter in the transpiled code:

  • The parameter counter inside increment.
  • The variable counter inside test.

They are pletely 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).

There are two things going on here:

  1. The function is passing the value of your variable and not the variable itself (as other answers have explained)
  2. The way in which babel transpiles const to var and still keeps the contract of not being re-assignable. I'll explain this part in my answer:

Why does Babel does not properly handle const?

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;
// bees
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;
// bees
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.

Ergo Babel does properly handle const

The reason why your code wasn't transpiled to throw an error is because of part 1.

发布评论

评论列表(0)

  1. 暂无评论