As a long time programmer just getting into JavaScript programming, I have the following questions that are still unclear despite having read many articles.
Looking at the ES6 (ECMAScript 2015) support by browsers, I can see that the supporting level is much less than that of Node.js, so the question is,
If both Node.js and browsers are using the modern V8 engine, why supporting level are so different?
Looking at the ES6 support in Node.js, I can see really really few ES6 features are unsupported now. However, what exactly does the supported means in the chart? I.e.,
Does it means even I write using the support ES6 features, I still need to use the Babel compiler to compile ES6 code to ES5 for Node.js to use it?
For TypeScript ES6-style JavaScript code that runs for Node.js, they are still need to be transpiled into an ES5 compatible form, despite that Node.js almost cover all ES6 featues, right? I.e.,
for the following code,
class Animal {
constructor(public name) { }
move(meters) {
console.log(this.name + " moved " + meters + "m.");
}
}
class Snake extends Animal {
move() {
console.log("Slithering...");
super.move(5);
}
}
class Horse extends Animal {
move() {
console.log("Galloping...");
super.move(45);
}
var sam = new Snake("Sammy the Python")
var tom: Animal = new Horse("Tommy the Palomino")
sam.move()
tom.move(34)
Does it need to be transpiled into an ES5 compatible form to runs with Node.js or not?
Finally, any online site that I can try playing with TypeScript/ES6 code like above?
I copy it to my chrome console, and got an error that I don't understand - Unexpected strict mode reserved word, and
I tried it on http://www.typescriptlang.org/play/index.html, but the console output is not working there.
Please help. thx.
Looking at the ES6 (ECMAScript 2015) support by browsers, I can see that the supporting level is much less than that of Node.js, so the question is,
Many different browsers and many different Javascript engines in them, each with their own level of ES6 support. The latest version of node.js is generally pretty up-to-date on what the V8 engine supports. Many browsers have longer release cycles and may not be as current, but each is different and has their own release strategy and level of ES6 support.
If both Node.js and browsers are using the modern V8 engine, why supporting level are so different?
If you compare the latest release of node.js with the latest release of Chrome on Windows, you won't see much difference in support. The ES6 support chart you're looking at seems old to me. For example, Chrome has had support for the Set object for a long time, but your chart says false.
Looking at the ES6 support in Node.js, I can see really really few ES6 features are unsupported now. However, what exactly does the supported means in the chart? I.e.,
Supported means you can use the feature directly without a transpiler, but how accurate that is depends upon the source of the document claiming it. Some documents do extensive testing of all the various edge cases of a given feature.
Others just look for general implementation. So if for example, you're looking at support for the Set object and it says "supported", then that is suppose to mean that you can just write plain Javascript that uses the Set object and it will just work. How accurate that document is depends upon the source of their data and the thoroughness of their testing.
Does it means even I write using the support ES6 features, I still need to use the Babel compiler to compile ES6 code to ES5 for Node.js to use it?
No. In a Javascript engine that supports a given feature in ES6, you can write ES6 code for that feature and directly run it in that Javascript engine. No transpiling is needed.
For TypeScript ES6-style JavaScript code that runs for Node.js, they are still need to be transpiled into an ES5 compatible form, despite that Node.js almost cover all ES6 featues, right? I.e.,
The class definitions you show are plain ES6 code. Those will work just fine as is in an ES6 capable Javascript engine.
If you write Typescript code, then you will have to transpile the TypeScript to Javascript because no Javascript engine (I know of) supports TypeScript directly. When transpiling form TypeScript to Javascript, you can usually specify whether you want the transpiler to generate ES5 compatible code (which will run in an ES5 engine or an ES6 engine) or ES6 compatible code (which will only run in an ES6 engine) depending upon what your target environment is capable of.
Does it need to be transpiled into an ES5 compatible form to runs with Node.js or not?
Your particular code appears to contain at least one TypeScript style variable declaration which would need to be transpiled. The rest looks like plain ES6 Javascript which should work in any ES6 engine without transpiling.
When I remove the TypeScript, fix some syntax errors in your code and implement the Animal constructor properly, then this code works fine in node.js v8.8.1 (which is what I currently have installed) and in Chrome 63.0.3239.132, Edge 41.16299.15.0 and Firefox 57.0.4 all on Windows 10:
// Generic ES6 code
class Animal {
constructor(name) {
this.name = name;
}
move(meters) {
console.log(this.name + " moved " + meters + "m.");
}
}
class Snake extends Animal {
move() {
console.log("Slithering...");
super.move(5);
}
}
class Horse extends Animal {
move() {
console.log("Galloping...");
super.move(45);
}
}
var sam = new Snake("Sammy the Python");
var tom = new Horse("Tommy the Palomino");
sam.move();
tom.move(34);
You can run this snippet yourself in any browser you desired to see the results (assuming the browser is modern enough to support a stack overflow snipppet). It works in all the current versions of browsers I have except IE 11.192.16299.0 (no surprise that IE doesn't support ES6).
I copy it to my chrome console, and got an error that I don't understand - Unexpected strict mode reserved word,
This happened to me when I tried to run your code in node.js until I removed the TypeScript from it so that it was just plain ES6. I think this particular error is caused by the public in this line:
constructor(public name) { }
since that is not part of the ES6 specification (it's apparently part of TypeScript).
It seems that there's one question you're dying to ask, but haven't exactly articulated is: "How do you know whether you have to transpile or not?".
The answer is that you have to understand the cross between the target environments you wish to run in and the newest features you plan to use. If you are writing server-side code that will only run in node.js, then it's a lot simpler. Examine a comprehensive table such as http://node.green/, study what it says for the node.js version you plan to use and the feature in question. If it indicates you should be able to use that feature, then write your code using that feature, write a test case for it and verify that both the code you wrote and the feature you are using both work. Add that to your body of knowledge about what you can and can't use in that version of node.js. You can then assume all future versions of node.js will also support that feature.
If you're writing code to run in a browser, life is much more complicated. If you plan to support a lot of browsers and really don't want to worry about ES6 support at all, then just transpile to an ES5 target and go about your business.
If you want to use non-transpiled code, then you have a lot of testing to do in a lot of browsers. You have to first specify exactly which versions of which browsers you are going to support and then you have to write your code and test cases and you have to test in every browser you plan to support. There really is no shortcut. When you find things that don't work, you'll have to either look for polyfills or work-arounds or stop using that ES6 feature.
Test the code in the environments that the code is going to be used in. Use the available means to implement the specific standard or specification within the environment that you are using the code at. Or try to create an approach yourself to resolve an issue that you encounter during development of your code while noting the progressions and persistent issue for others to be able to possibly address and resolve the issue, bug or requirement from their own perspective.
Simply due to the fact the a document states that the browser has implemented a specification or standard does not mean that the implementation is consistent with the specification, or implemented at all. The only way to verify whether a browser implements a standard is to test with code yourself. File issues and attempt to fix bugs yourself.
Browsers use different engines including Gecko, WebKit, not V8 alone; and can change over time in both name and implementations of specifications; see Monitor and potentially deprecate support for multitrack SourceBuffer support of 'sequence' AppendMode; How to use "segments" mode at SourceBuffer of MediaSource to render same result at Chomium, Chorme and Firefox?. There are many browsers. For example, Lynx does not use V8.
See web platform tests
The web-platform-tests Project is a W3C-coordinated attempt to build a
cross-browser testsuite for the Web-platform stack. Writing tests in a
way that allows them to be run in all browsers gives browser projects
confidence that they are shipping software that is compatible with
other implementations, and that later implementations will be
compatible with their implementations. This in turn gives Web
authors/developers confidence that they can actually rely on the Web
platform to deliver on the promise of working across browsers and
devices without needing extra layers of abstraction to paper over the
gaps left by specification editors and implementors.
For example, one test for Web Speech API, where volume property is specified as capable of being set, though was not able to detect a change of audio output for either Chromium or Firefox when setting the volume property of SpeechSynthesisUtterance to different values within the specified ranges.
Specifications are a totally different regime than actual browser implementations. Specifications or standards can be and are written well in advance of actual browser implementation, if implemented at all. You can use browserify, or write the code yourself to use NodeJS modules or other non-native code in the browser.
Related
I have been reading through a book called You don't know JS and one thing that I can't wrap my head around is the concept of backward compatible and forward compatible Javascript.
From what I understand:
Backward Compatible: Once something is added to Javascript specification, it would never become invalid JS in future
Forward Compatible: Including a new addition to the language in a program would not cause that program to break if it were run in an older JS engine
Javascript is backward compatible and not forward compatible. This means that while including new feature in a program might break the program (forward compatible), Javascript engines would support older syntax forever in future (backward compatible).
To solve a problem of forward compatible issue, developers use transpilation and polyfills to convert new syntax to an older syntax supported in older Javascript engine.
So if transpilation is used to convert code into forward compatible code, does that mean Babel is used to solve forward compatibility issue and not backward compatibility issue?
This comes from the official doc in Babel website:
Babel is a toolchain that is mainly used to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript in current and older browsers or environments.
I must have missed something and need some clarification on how to think through this.
Edit 1
I thought it would be helpful to quote parts of the book here:
Typically, forwards-compatibility problems related to syntax are solved by using a transpiler (the most common one being Babel (https://babeljs.io)) to convert from that newer JS syntax version to an equivalent older syntax.
Developers should focus on writing the clean, new syntax forms, and let the tools take care of producing a forwards-compatible version of that code that is suitable to deploy and run on the oldest-supported JS engine environments.
I believe your confusion is rooted in the mixing of the forwards- and backwards-compatibility terms for both the operating environment or language, and individual scripts themselves.
In the You Don't Know JS doc, the writer is describing the implementation of the language as whole as being backwards compatible, in the same way that many video games released for early generations of consoles (such as PlayStation and XBox) are able to played on their more recent successors (PlayStation 2 and XBox 360) due to the console (and its architecture, operating system, etc) being backwards compatible. When applied to JS, this means that a browser implementing a newer version such as ECMAScript 2015+ will fully support code written using an older version.
Babel, on the other hand, is referring to the code itself, and being able to create a backwards compatible version which can be run on older browsers, for example. To expand on the example above, this would be akin to being able to process an XBox 360 game through some engine (i.e. Babel) and have it give you a fully functional game to play on your original XBox. This is clearly a much more difficult problem, but is required due to JS not being forward-compatible.
When you crate a new Google Apps Script, it seems to support the v8 runtime by default. The documentation states:
Apps Script supports two JavaScript runtimes: the modern V8 runtime and an older one powered by Mozilla's Rhino JavaScript interpreter.
The V8 runtime supports modern ECMAScript syntax and features.
The V8 runtime documentation states:
You can use modern ECMAScript syntax in scripts that are powered by the V8 runtime. This syntax includes let, const, and many other popular features.
In both cases, they are very vague as to which ECMAScript version is supported, simply stating "modern ECMAScript syntax". This is problematic because there are 7 versions that were released between 2015 and 2021. Thus "modern" could refer to any one of these versions.
For example, I could easily assume that "modern" refers to the latest, 12th edition (2022) of ECMAScript, and end up writing code like this:
let a = 1_000;
However, attempting to use that syntax leads to the error:
Syntax error: ParseError: Unexpected token ILLEGAL line: ...
Rather than manually go through each of the remaining 6 versions until I find the latest one supported, it would be great to find documentation that explicitly states which ECMAScript version is supported.
Note: The previous related question (Which Edition of ECMA-262 Does Google Apps Script Support?) is not helpful since those answers also refer to "modern ECMAScript" rather than a definitive, specific version.
Which version of ECMAScript is supported by the V8 runtime?
There is some nuance here:
Which version of V8 does Google Apps Script use?
A reasonably recent version, and it gets updated every so often. I believe the idea is to track or slightly lag behind stable Chrome releases, but (as with any large project updating its dependencies) there may occasionally be hiccups/delays. Right now it should be somewhere in the 9.x version range. (For future readers: I expect this statement to be outdated before 2022 is over!)
Which version of ECMAScript does the Google Apps Script V8 Runtime Support?
I suppose if there was a simple answer to this, you'd find that in the documentation. As #Kaiido said in comments, JavaScript engines implement new JavaScript features one by one (rather than EcmaScript versions). So, for browsers just like for environments like GAS, it usually makes more sense to ask "is feature X supported?", because it may well be that some, say, ES2020 features are still missing but some ES2021 features are already available.
Why does let a = 1_000; produce a Syntax Error?
Well, the V8 version that GAS uses is sufficiently new (by at least two years) to support it; but the overall GAS experience depends on more than V8: the editor is parsing the entered source in order to provide help or highlighting or error checking or whatnot. It looks like the GAS team is aware that certain features aren't supported yet by the components responsible for that, and is actively working to remedy that. (I have no idea what the timeline is.)
Why does let a = 1_000; produce a Syntax Error?
Just to expand on #jmrk's answer about new features not supported by the parser.
function test2564(){
//let a = 1_000; throws syntax error by the parser
console.info(eval(`1_000`));// correctly logs 1000
}
The underlying V8 engine is good and supports the latest features, but the parser won't allow you to save or execute the project with those features, as it considers them as syntax errors.
I work at a company where we use ReSharper 2016 extensively to inspect and refactor our C# code, and we would now like to use those same tools to ensure the quality of our javascript.
We're supporting IE, so ES6 features are out, however when the inspection language is set to ES5 in ReSharper's options and warnings are set for unsupported language features (as in the image below) only some ES6 features are being flagged up.
So, for example, let and const are highlighted with an error, however lambda functions are not. Default parameters are highlighted, but Array.find() is not, and so on. It seems fairly arbitrary what is and what isn't detected.
Is there some additional configuration needed, or am I perhaps misunderstanding something about the ES6 feature set? How can I ensure all ES6 features result in errors?
There are many ES6 features that look great like => syntax, Map object, and a long etc.
To be honest I'm kind of tired of checking if there is support for addEventListener due to ie8 attachEvent, and I wouldn't like that kind of pain coming back to my life.
So how, would you deal with this new posibilities? (or how will you, lets say, in a year or so). Would you not use them for basic actions but to add another layer of extra functions? Would you use it just for apps that you know you will be running in browsers that support them? Would you wait untill there is at least 90% of support?
I understand these are great features but for short to medium term usage it seems that you'd need to double your code checking and fallbacking for support.
Any enlightment about this subject?
EDIT: Please, don't mark this as duplicate. Notice I'm not asking how to check for support, I'm asking if it is wise to start using it, or it is better to wait. I'm also asking if the support check is the best option, not how to do it, or if there are other ways to proced while designing your code.
tl;dr: Make use of transpilers and polyfills.
Whether or not you should use new features primarily depends on your target environment and how exactly you are using new features. E.g. if you are targeting only the latest browser version, then you won't have an issue. Have to support IE8? That could be more difficult.
In general though, you should start using new features as soon as possible, and make use of tools that help you with that.
There are two aspects to look at:
New APIs
New syntax constructs
APIs
New API's can often (but not always) be polyfilled. I.e. you include a library which checks whether certain parts of the API exist, e.g. Map, and provides an alternative implementation if it doesn't.
These alternative implements may not be 100% equivalent or may not be as performant as a native implementation, but I'd say they work for 95% for all use cases.
The nice thing about polyfills is that you will be automatically using the native browser implementation if it is available.
Syntax
Making use of new syntax constructs, such as arrow functions or classes, is a bit more complex (but not much). The biggest issue is that browsers who do not support the syntax cannot even evaluate your code. You can only send code to the browser that it can actually parse.
Fortunately many of the new syntax elements, such as arrow functions, are really just syntactic sugar for things that are already possible ES5. So we can convert ES6 code into their ES5 or even ES3 equivalent.
Several such tools, called transpilers, have emerged over the last one or two years. Note that the transpiler has to convert your code before it is sent to the browser. This means that instead of simply writing your JS file and directly include in your page, you need to have a build step that converts the code first (just like we have in other languages, like C or Java).
This is different from how we wrote JS a couple of years ago, but having a build step has become increasingly more accepted by the JS community. There are also many build tools that try to make this as painless as possible.
One drawback is, unlike with polyfills, that you won't magically be using the native features if they become available. So you could be stuck with shipping the transpiled version for a long time, until all your target environments support all the features you need. But that's probably still better than not using the new features at all.
You can use BabelJS or Google Traceur
You have to include in your build process a step to transform ES6, ES7 code to Javascript compatible with todays browsers. Like a gulp or grunt task. Babel has a list of supported tools here
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 months ago.
Improve this question
I've just read some advertisement information related to TypeScript and besides that I have no experience with this superset of JavaScript. So I have some basic questions:
What is the status of native TypeScript support by the modern browsers?
What are the positions of the major browser vendors for the future support of TypeScript natively?
What is the relation between TypeScript and ECMAScript 6 and does TypeScript provide much more features than ECMAScript 6?
Native support
Native support can be added quite easily e.g. https://github.com/basarat/typescript-script adds support for script tags (although this adds 6 MB of supporting JavaScript to a page). However there is a performance hit in compiling TypeScript to JavaScript and for the best performance it is best to precompile and execute the compiled JavaScript in the browsers.
Browser vendors have no plans to add native TypeScript support. The only native languages common across browsers are JavaScript and WebAssembly. TypeScript can be transpiled to either and run in the browsers so its not a blocker.
Not-native support
What is the status of TypeScript support by the modern browsers?
TypeScript compiles to JavaScript, so it's supported by all browsers (even Internet Explorer 6).
What are the positions of the major browser vendors for the future support of TypeScript?
No work is needed on behalf of browser vendors.
What is the relation between TypeScript and ECMAScript6 and does TypeScript provide much more features than ECMAScript6 ?
Yes, e.g., from future JavaScript versions, e.g., class fields and static properties in classes.
Trying to design a web browser that could natively support more than one language at a time is exactly what Google tried to do with Dart. There was a Dart engine planned for Chrome, but this ended up being too big a task with very little benefit aside from "just not using JavaScript".
I suspect supporting TypeScript natively would be an equally daunting task. Probably better to just improve upon ECMAScript and add in a few TypeScript ideas where they make sense. I do love TypeScript though.
TypeScript cannot be run or understood in any browser. So, TypeScript is compiled to JavaScript (which browsers can understand). TypeScript can use all ECMAScript 2015 features and during the compilation they will be converted to target compile options like ES5.
Currently it won't work, but it's an interesting topic though. It would be good to know if at some point ECMAScript is going to support interfaces, types and other things. Especially, I can notice that ECMAScript actually slowly takes some parts from the TypeScript, e.g. enums.
If it would work, I'd rather see it as ECMAScript taking some stuff from TypeScript rather than natively supporting TypeScript itself.
I know it's currently not supported and there are no plans to support TypeScript natively in the browser but there is a huge (in my opinion) problem with tooling in the frontend (JavaScript) ecosystem - there's too much of it. Bundling, module resolution, transpiling, and more.
I think it makes development much slower, because there are a lot of issues with configurations, versions mismatch, compatibility and a lot of obscure issues (Stack Overflow and GitHub are full of such topics) that stem from the tooling, not implementing features.
I would call it a crisis, but it has been like this for a while and I know this is the way of doing things now.
I think there are a few things that need to happen.
We need to be able to use native ES6 modules (import/export) in the browser. I know it's supported, but only a relative or URL imports work. I know there is work on "import maps" or whatever they are called.
It would be great if browsers (Chrome) can read TypeScript code. It doesn’t have to interpret or enforce any typing - essentially treat it like JavaScript with some additional nonsense that the browser just ignores. It could be just a "developer mode" in the browser but we would be able to achieve 0-transpiling during development.
Simplify eager resource loading (to avoid bundling)
Again, this is just for development benefit. I know a lot of these tools have their place in production builds, older browser support, etc.