Why are ES6 classes not hoisted?
Actually they are hoisted (the variable binding is available in the whole scope) just likeWhy are ES6 classes not hoisted?
let
and const
are - they only are not initialised.No. It's never a good idea to use a class before its definition. Consider the exampleIt would make sense to hoist its definition
var foo = new Bar(); // this appears to work
console.log(foo.x) // but doesn't
function Bar(x) {
this.x = x || Bar.defaultX;
}
Bar.defaultX = 0;
and compare it tovar foo = new Bar(); // ReferenceError
console.log(foo.x);
class Bar {
constructor (x = Bar.defaultX) {
this.x = x;
}
}
Bar.defaultX = 0;
which throws an error as you would expect. This is a problem for static properties, prototype mixins, decorators and everything. Also it is quite important for subclassing, which broke entirely in ES5 when you used a class with its non-adjusted prototype, but now throws an error if an extend
ed class is not yet initialised. Why are javascript functions within classes not hoisted?
class A { f1() { return f2() } f2() { return 'f2' }}
var a = new A()
console.log(a.f1())
How to get hoisting to work for extended classes?
In the related link is an example with the Hero class. There are many answer here in stackoverflow, that are telling, that classes are hoisted and that this behaviour changed between ES5 and ES6. Take a look at this answer: Why are ES6 classes not hoisted?Yes but no. It is correct that the class name is hoisted. However, that it rather irrelevant to your situation.
Javascript is executed in two steps:
- Parsing/compilation
- Runtime
MyActionEdit
will be created in the correct scope. That is what hoisting is. Because in the second step, the runtime, when the code actually runs, that name will already exist, even if it comes later in the scope:console.log(foo);
var foo = 'bar';
What is the correct placement of constructors or classes in JS code?
A variable is just a means to store and reference a value. An object is a type of value. A function is a type of object. A constructor function is a function designed to be called with the new
keyword (which creates an object and sets up the prototype chain on it).
To call a constructor function, you need to have access to that value. This can be via a variable (and usually is).
The variable must contain the constructor function before you can reference it.
A function declaration is a means to create a function, which can be a constructor function, which is hoisted, allowing it to be used earlier in the code then it appears.
However, constructor functions typically have a number of methods added to the prototype and these are not hoisted so in the example below:
- The instance of dog is successfully constructed
- The attempt to bark fails because the assignment to prototype.bark hasn't happened yet
var fido = new Dog("Fido");fido.bark();
function Dog(name) { this.name = name;}
Dog.protype.bark = function () { alert(`Woof! I'm ${this.name}`);}
Typescript class: will class be hoisted when I use two classes?
The reason is that this line:
hero = new Hero('foo')
Is only evaluated when you instantiate AppComponent
which is after the class Hero
has been evaluated.However, in your 2nd code snippet this line:
const b = new Bolygon();
Is evaluated first, before the class itself has been evaluated. If you make AppComponent.hero
static it will cause an error:
class AppComponent {
static hero = new Hero('foo') // errro: Hero is not a constructor
}
Bundling ES6 classes with Webpack. Is there a way to hoist extended classes?
Webpack does not simply put all the imports together into one file, but it keeps them as modules. Every module/file needs to import everything it depends on, so it would work if you just run that module in Node (after transpiling if necessary). Your a.js
does not work by itself because classD
is not defined. The correct way is to import it in a.js
:
import ClassD from './d';
export default class ClassA extends ClassD {
constructor(...) {
super(...);
}
}
import x from './file'
imports the default export as x
, so you want to use export default
for your classes.You might be worried that importing a file from multiple places will include it multiple times, but that is not the case, it's included once and every import of that module will refer to the same one in the bundle.
Note: The convention in JavaScript is to use PascalCase for classes.
Are ES6 classes just syntactic sugar for the prototypal pattern in Javascript?
Yes, perhaps, but some of the syntactic sugar has teeth.
Declaring a class creates a function object that is the constructor for the class, using the code provided for constructor
within the class body, and for named classes, with the same name as the class.
The class constructor function has a normal prototype object from which class instances inherit properties in normal JavaScript fashion. Instance methods defined within the class body are added to this prototype.
ES6 does not provide a means to declare class instance default property values (i.e. values which are not methods) within the class body to be stored on the prototype and inherited. To initialize instance value you can either set them as local, non inherited properties within the constructor, or manually add them to the class constructor's prototype
object outside the class definition in the same fashion as for ordinary constructor functions. (I am not arguing the merits or otherwise of setting up inherited properties for JavaScript classes).
Static methods declared within the class body are added as properties of the class constructor function. Avoid using static class method names that compete with standard function properties and methods inherited from Function.prototype
such as call
, apply
or length
.
Less sugary is that class declarations and methods are always executed in strict mode, and a feature that gets little attention: the .prototype
property of class constructor functions is read only: you can't set it to some other object you've created for some special purpose.
Some interesting stuff happens when you extend a class:
the
prototype
object property of the extended class constructor is automatically prototyped on theprototype
object of the class being extended. This is not particularly new and the effect can be duplicated usingObject.create
.the extended class constructor function (object) is automatically prototyped on the constructor function of the class being extended, not
Function
. While it may be possible to replicate the effect on an ordinary constructor function usingObject.setPrototypeOf
or evenchildClass.__proto__ = parentClass
, this would be an extremely unusual coding practice and is often advised against in JavaScript documentation.
function
keyword.I believe it could be naive to think that Class declarations and expressions will remain unaltered in all future versions of ECMA Script and it will be interesting to see if and when developments occur. Arguably it has become a fad to associate "syntactical sugar" with classes introduced in ES6 (ECMA-262 standard version 6) but personally I try to avoid repeating it.
Related Topics
Angularjs Browser Autofill Workaround by Using a Directive
Javascript: Cancel/Stop Image Requests
How to Parseint a String with Leading 0
How to Sign into Google with Selenium Automation Because of "This Browser or App May Not Be Secure."
Why Does If("String") Evaluate "String" as True But If ("String"==True) Does Not
How to Compare 2 Functions in JavaScript
Regular Expression for Url Validation (In JavaScript)
JavaScript Array Concat Not Working. Why
Accessing JSON Object Keys Having Spaces
Do Websockets Allow for P2P (Browser to Browser) Communication
Create File with Google Drive API V3 (Javascript)
Adding New Data to Firebase Users
Can Promises Have Multiple Arguments to Onfulfilled