Freigeben über


Classes in JavaScript: Exploring the Implementation in Chakra

The Windows 10 Technical Preview November build and RemoteIE includes many changes and additions to Internet Explorer from the next edition of the JavaScript standard, ECMA-262 6th Edition (ES6). ECMAScript 6 will be a substantial advance for JavaScript language, and currently the technical preview is the most compliant implementation. This post explores where ECMAScript is going and gives a peek into the implementation of a new language feature: ES6 Classes.

ECMAScript Evolution to Meet the Advancing Web

The web has evolved substantially in the 5 years since ES5 was ratified. Apps today are becoming more complex and demanding. Microsoft, working with the ECMA working group - TC39, has been hard at work on the next substantial update to the language. The 6th edition of ECMA-262 (ES6) is perhaps the biggest update to the language in its history.

The order we implement ECMAScript proposals depends on a few principles including whether it is necessary to ensure interoperability with other engines, enables new types of apps, provides developers with compelling value beyond saving keystrokes, has a stable specification has multiple reference implementations, and has a comprehensive test suite (called Test262) to ensure interoperability. Overall we do our best to make data driven decisions and deliver features that will give the most value to developers. Let us know what you find most valuable on User Voice or Connect!

ES6 Classes

Many features in ES6 aim to reduce time writing code and increase expressiveness of common patterns in JavaScript. Because they do not add new fundamental capabilities to the runtime and essentially simplify the boilerplate code, these kinds of features are collectively referred to as ‘syntactic sugar’.

ES6 Classes in JavaScript is one such feature and remains one of the most commonly requested features on status.modern.ie.

To those of you familiar with object-oriented languages, classes should be a familiar concept. However classes in JavaScript are a little different from other languages. With ES5, class functionality is commonly implemented using functions, prototypes, and instances. For example:

By contrast, the ES6 version below is much more readable and concise. For programmers from a classical inheritance background, the functionality is easier to understand without in depth knowledge of how JavaScript's prototypal inheritance model works.

Now that we’ve seen a simple example of what the syntax looks like, let’s have a look at the other syntactic features of ES6 classes.

The example includes a basic class construct with instance, static, getter and setter methods. A class constructor is a special method which can be customized or omitted. Omitting a constructor generates the default constructor which merely forwards arguments to its super as shown above. Classes provide inheritance through the extends keyword. A subclass has the super keyword, which allows use of the superclass properties and methods.

Implementation challenges

In a previous post, we explored the architecture of the Chakra engine in detail (see ‘Announcing key advances to JavaScript performance in Windows 10 Technical Preview ) using the diagram below. The parts requiring the most modification to support classes are highlighted in green.

Parts of the Chakra engine requiring the most modification to support ES6 Classes

When implementing new language features, syntactic sugar features often map directly to older language constructs, as shown in the first code example. Classes are no exception. Underneath, classes use the same function, prototype, and instance constructs that have always been available, and Chakra uses these constructs to implement classes.

Not all of the sugar maps to pre-existing language features, however. The super keyword is one example. super ended up taking longer than the rest of classes due to its complex usage scenarios. These uses are not always apparent to the end user, but part of the fun of being a compiler developer is to come up with the corner cases that break things. For example, the use of eval() in a class makes the implementation more complex:

In the example above, both Child methods require a reference to Parent to allow execution of super(). In the case of method(), the parser is able to detect the use of super() at compile time. Chakra marks method() as having a super keyword reference during parsing, so when it reaches bytecode generation it knows to generate special bytecode to make a reference to Parent available. At runtime, this reference becomes available as Chakra consumes the bytecode at the beginning of the function, performing checks on whether it is valid to use super at that location and point in time.

In the case of methodEval(), there is a call to eval() which drastically changes the implementation. Chakra knows this is a class method, but until it executes the eval(), it has no idea if there is a super reference, or if there will ever be a super reference. This poses a design problem that we felt had two options:

  1. Should Chakra maintain a reference to Parent that is available in case it is needed by super somewhere inside the eval(), or
  2. Should Chakra wait until it is somewhere in the eval()to fetch the reference?

The first option, pre-emptively loading super, adds unnecessary bytecode to the method which could adversely affect performance.

The second option, to fetch the Parent reference when Chakra needs it, sounds simple at first. However it can’t predict the complexity of the eval(). For example, Chakra could be several levels deep in function calls in the eval(), or perhaps be in several levels of the eval()itself. Finding the Parent reference at this point could be more costly than if it had been stashed it away previously.

There isn’t necessarily a correct answer here, and the answer may change as we learn more about how programmers use super. In the current technical preview, we implemented super by pre-emptively loading the reference in situations where the trade-off in performance is justifiable. For example, using super in a subclass method is more likely to happen than in a top level class method (regardless of whether the use is valid or invalid.)

In the time since the release of the technical preview, the ES6 specification has been updated to allow super in more places. Being on the bleeding edge of implementation as standards evolve often means revisiting implementations, and the ES6 specification is no different.

Classes are a core part of the ES6 language feature set. We anticipate they will help new JavaScript programmers learn the language more rapidly when they have experience with other object oriented languages. We also anticipate that many seasoned JavaScript programmers will welcome the terseness.

Moving forward with ECMAScript

While ECMAScript 6 makes great progress, both the runtime capabilities and expressivity will continue to evolve. ECMAScript 7 should arrive more rapidly than any previous ECMAScript version because it and future editions of the standard will be moving to a more regular “train model”. In this model, proposals are built in isolation from one another and move through stages of ratification as they mature. Eventually, a proposal may make it on to a “train”, where the proposal is integrated with the other proposals on the train to form the final document that will be ratified. This model is useful for language standards because we get cohesive, complete specifications developed in an agile fashion that we don’t have to wait years for. It also gives some flexibility to make sure we get a design right. It’s a lot easier to take a bit more time when it means shipping in the specification next year rather than five years from now. For example, when the committee got substantive negative feedback on the subclassing built-ins machinery, it was relatively easy to pull it out of ES6 and get it ready for making the ES7 train. (You may also be interested to know that we were analyzing a subclassable built-ins implementation to complement classes, but as a result of the change we could not include it in this release.)

This model should also be much friendlier to JavaScript developers because new features come to the language yearly rather than every half decade. Also, browsers can pick up smaller chunks and begin implementing them sooner in the process, which should help get interoperable implementations more rapidly. The end result of this new process should be substantially increased pace of improvements to JavaScript.

Summary

Classes are available today in the current Windows 10 Technical Preview, and you can also play with them using remote.modern.ie. We can’t wait to hear about how you will be using the feature in your ES6 code. We’re planning to deliver more articles in the future about other ES6 features. In the meantime, feel free to join the comment discussion, reach out on Twitter @IEDevChat, or on Connect.

Tom Care (@tcare_), Brian Terlson (@bterlson) & Suwei Chen

Chakra Team

Comments

  • Anonymous
    December 16, 2014
    Have we gone too far? At what point does javaSCRIPT do too much?

  • Anonymous
    December 16, 2014
    Wow, Nice work, love the new improvements, it is nice to see IE leading again in development features, thank you. Note: I am a Software Developer that is moving back from Chrome to IE.

  • Anonymous
    December 16, 2014
    can you use namespaces? Class NamespaceOrObject.ClassName { // class defenition }

  • Anonymous
    December 16, 2014
    @OldDude Hard to say definitively as it probably depends on what you need the language for. But I don't think we're nearing "too much" for JS on the Web or on the server, for example. These areas have lots of room for improvements. @GTX: You can't use namespaces in the declaration. But you can use class expressions like the following: NamespaceOrObject.ClassName = class {    // class definition }

  • Anonymous
    December 16, 2014
    Interestingly, the ES5 sample works without these lines, SuperHero.prototype = Object.create(Civilian.prototype); SuperHero.prototype.constructor = Civilian;

  • Anonymous
    December 16, 2014
    @Sean Gephardt: True! Each part is important though. The Object.create part makes sure your subclass has the superclass prototype in its prototype chain. The example is unaffected because it doesn't attempt to call a superclass method on the subclass instance. The .constructor part is needed when replacing the prototype so the "instanceof" operator works properly.

  • Anonymous
    December 16, 2014
    @Microsoft What happened to KB3008923 problem more than such thing? Investigate the cause rather early and please distribute a correction program. There seems to have been a lot of trouble by an update this month in particular, doesn't there?

  • Anonymous
    December 16, 2014
    @Brian Terlson [msft] Thanks for the replay NamespaceOrObject.ClassName = class { ... Sounds good as well :)

  • Anonymous
    December 18, 2014
    Thanks for writing a clean code sample (and even using Github's tools for great syntax highlighting etc. I'm so glad that this blog no longer publishes garbage with UPPER_CASE html tag names, camelCase attributes and outdated C-syntax bracing vs. JavaScript/ECMAScript (K&R style) bracing and inline callbacks. Awesome work IE Team!

  • Anonymous
    December 18, 2014
    You guys should consider supporting TypeScript and CoffeeScript, so to avoid server side transformation.

  • Anonymous
    December 19, 2014
    One of the pillars of JavaScript is objects without classes, and it's no secret that classes often do more harm than good (just google "classical inheritance considered harmful") for lots of opinions. I go into a lot of detail about why you may want to avoid the class keyword altogether here: medium.com/.../the-two-pillars-of-javascript-ee6f3281e7f3 Any comment?

  • Eric Elliott, author, "Programming JavaScript Applications" (O'Reilly)
  • Anonymous
    December 19, 2014
    Chakra nightly might be good at handling classes but the Trident input and memory model surely is in a real bad shape (as always). IE team should consider revamping it. It gets too obvious, when you are running multiple programs and tabs in IE and then lets say you browse to a large diff (aka: "changes") view on GitHub: github.com/.../files, use keyboard arrow (or even mouse) to scroll down the page and observe the "slow motion", "jittering", "content missing for a while" kinds of abnormalities. Open the same link in any non-IE browser, with equal number of tabs open there and observe the scrolling behavior. Unfortunately, except for IE team and IE fanboys, everyone in the world can reproduce this kind of issue. Oh and in case you are wondering, just search "performance" and / or "scrolling" on Connect and you will find tons of issues with more enlightening reproduction steps there (some are dated 2006/7). They say 100 tabs are limit, my i7-gen4-6GB-RAM with HDD (no-SSD) starts to show up with 30-40 tabs. Chrome with this amount of tabs behave well.

  • Anonymous
    December 20, 2014
    The comment has been removed

  • Anonymous
    December 21, 2014
    Please can you clarify this: Edge is new rendering engine or its mode? Trident Engine with Edge Mode?

  • Anonymous
    December 21, 2014
    The comment has been removed

  • Anonymous
    December 22, 2014
    Actually I'm sorry. I really don't know even 5 tabs currently loaded in my Chrome. I've just forgot I can visite those links again and favorite them in case I close all tabs in the browser. By the way, I love spent my machine resources with tabs I will not use anymore. I've already spend my time with Chrome crashing in so many sites. Perhaps I should change back to IE.

  • Anonymous
    December 23, 2014
    >>"Make your browsing 14x safer for the holidays!" Really? That's also good, but please exhibit information about Windows 10 and IE12 for Windows 7 early. Extension of main support for 1 year for 7, please.

  • Anonymous
    December 23, 2014
    @jason I tried your github link and it takes about 2 seconds to load and then scrolls fine in IE11 using mouse or quick use of page down key

  • Anonymous
    December 24, 2014
    The comment has been removed

  • Anonymous
    December 24, 2014
    The comment has been removed

  • Anonymous
    December 26, 2014
    @Vitor You mean just like chrome taking up 2+ gb of memory when you have a few tabs open.

  • Anonymous
    December 28, 2014
    Sorry I mean IE.

  • Anonymous
    December 28, 2014
    @vitor No issues with using the CTRL+END and/or CTRL+HOME on that githup page. The rendering is instant in IE11. I can go up and down that page as many times as the speed I can change from HOME to END key (about 150-200 times a minute or so)

  • Anonymous
    December 28, 2014
    Debugging in IE F12 is not as "fun" as in Chrome. For instance, if you enter $("a.active") in console, Chrome gives you an expandable presentation of each a.active element separately, with tiny navigation links and so forth. IE11's F12 shows an [object] blob. Please also take inspiration from Firebug, console, they way they present Ajax calls (loader gif, request, response, cookies, sessions, response preview as XML as well as HTML). This makes our lives real easy. MS is committed to make our lives easy, right? So here is another opportunity. To the fan boys, (who have committed their lives to protect every blunder made by IE team) hope i haven't hurt your feelings this time. :'(

  • Anonymous
    December 29, 2014
    The comment has been removed

  • Anonymous
    December 29, 2014
    @Gérard Talbot, +920! Adding to your 3a: it would be really nice to have GH like markdown editor on MSDN blogs and super GREAT to have the same on Connect! See this connect.microsoft.com/.../fall-update-c99-visual-studio-2013-update-3-fixed-1-2-of-the-union-issue. It reads like: ##############  Since Microsoft Connect team can't build a Markdown editor like GitHub  so to prettify code ############### (followed by the code) CodePlex team at Microsoft built web-based Markdown editor back in 2009. In early 2014, MadsKristensen's extension for VS called WebEssentials2013, brought Markdown editor support to the table, which even provides intellisense for VB,  C#, JS, CoffeeScript, TypeScript, CSS, SCSS, LESS etc. (which is a HUGE deal if you think about it)! Seems like "collaboration" is the concept, only exercised in SharePoint world in the Microsoft universe! Sorry fanboys, I am b*thcin again. I just wish IE and other M$ stuff become hipster enough to survive 2015 like a champ! I apologies if this hurt your feelings.. :'(