# Classes
Baseline Widely available *
This feature is well established and works across many devices and browser
versions. It’s been available across browsers since March 2016.
* Some parts of this feature may have varying levels of support.
* Learn more
* See full compatibility
* Report feedback
Classes are a template for creating objects. They encapsulate data with code
to work on that data. Classes in JS are built on prototypes but also have some
syntax and semantics that are unique to classes.
For more examples and explanations, see the Using classes guide.
## Description
### Defining classes
Classes are in fact "special functions", and just as you can define function
expressions and function declarations, a class can be defined in two ways: a
class expression or a class declaration.
// Declaration
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
// Expression; the class is anonymous but assigned to a variable
const Rectangle = class {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
// Expression; the class has its own name
const Rectangle = class Rectangle2 {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
Like function expressions, class expressions may be anonymous, or have a name
that's different from the variable that it's assigned to. However, unlike
function declarations, class declarations have the same temporal dead zone
restrictions as `let` or `const` and behave as if they are not hoisted.
### Class body
The body of a class is the part that is in curly braces `{}`. This is where
you define class members, such as methods or constructor.
The body of a class is executed in strict mode even without the `"use strict"`
directive.
A class element can be characterized by three aspects:
* Kind: Getter, setter, method, or field
* Location: Static or instance
* Visibility: Public or private
Together, they add up to 16 possible combinations. To divide the reference
more logically and avoid overlapping content, the different elements are
introduced in detail in different pages:
Method definitions
Public instance method
getter
Public instance getter
setter
Public instance setter
Public class fields
Public instance field
`static`
Public static method, getter, setter, and field
Private properties
Everything that's private
**Note:** Private properties have the restriction that all property names
declared in the same class must be unique. All other public properties do not
have this restriction — you can have multiple public properties with the same
name, and the last one overwrites the others. This is the same behavior as in
object initializers.
In addition, there are two special class element syntaxes: `constructor` and
static initialization blocks, with their own references.
#### Constructor
The `constructor` method is a special method for creating and initializing an
object created with a class. There can only be one special method with the
name "constructor" in a class — a `SyntaxError` is thrown if the class
contains more than one occurrence of a `constructor` method.
A constructor can use the `super` keyword to call the constructor of the super
class.
You can create instance properties inside the constructor:
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
Alternatively, if your instance properties' values do not depend on the
constructor's arguments, you can define them as class fields.
#### Static initialization blocks
Static initialization blocks allow flexible initialization of static
properties, including the evaluation of statements during initialization,
while granting access to the private scope.
Multiple static blocks can be declared, and these can be interleaved with the
declaration of static fields and methods (all static items are evaluated in
declaration order).
#### Methods
Methods are defined on the prototype of each class instance and are shared by
all instances. Methods can be plain functions, async functions, generator
functions, or async generator functions. For more information, see method
definitions.
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
// Getter
get area() {
return this.calcArea();
}
// Method
calcArea() {
return this.height * this.width;
}
*getSides() {
yield this.height;
yield this.width;
yield this.height;
yield this.width;
}
}
const square = new Rectangle(10, 10);
console.log(square.area); // 100
console.log([...square.getSides()]); // [10, 10, 10, 10]
#### Static methods and fields
The `static` keyword defines a static method or field for a class. Static
properties (fields and methods) are defined on the class itself instead of
each instance. Static methods are often used to create utility functions for
an application, whereas static fields are useful for caches, fixed-
configuration, or any other data that doesn't need to be replicated across
instances.
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
static displayName = "Point";
static distance(a, b) {
const dx = a.x - b.x;
const dy = a.y - b.y;
return Math.hypot(dx, dy);
}
}
const p1 = new Point(5, 5);
const p2 = new Point(10, 10);
p1.displayName; // undefined
p1.distance; // undefined
p2.displayName; // undefined
p2.distance; // undefined
console.log(Point.displayName); // "Point"
console.log(Point.distance(p1, p2)); // 7.0710678118654755
#### Field declarations
With the class field declaration syntax, the constructor example can be
written as:
class Rectangle {
height = 0;
width;
constructor(height, width) {
this.height = height;
this.width = width;
}
}
Class fields are similar to object properties, not variables, so we don't use
keywords such as `const` to declare them. In JavaScript, private properties
use a special identifier syntax, so modifier keywords like `public` and
`private` should not be used either.
As seen above, the fields can be declared with or without a default value.
Fields without default values default to `undefined`. By declaring fields up-
front, class definitions become more self-documenting, and the fields are
always present, which help with optimizations.
See public class fields for more information.
#### Private properties
Using private fields, the definition can be refined as below.
class Rectangle {
#height = 0;
#width;
constructor(height, width) {
this.#height = height;
this.#width = width;
}
}
It's an error to reference private fields from outside of the class; they can
only be read or written within the class body. By defining things that are not
visible outside of the class, you ensure that your classes' users can't depend
on internals, which may change from version to version.
Private fields can only be declared up-front in a field declaration. They
cannot be created later through assigning to them, the way that normal
properties can.
For more information, see private properties.
### Inheritance
The `extends` keyword is used in _class declarations_ or _class expressions_
to create a class as a child of another constructor (either a class or a
function).
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
constructor(name) {
super(name); // call the super class constructor and pass in the name parameter
}
speak() {
console.log(`${this.name} barks.`);
}
}
const d = new Dog("Mitzie");
d.speak(); // Mitzie barks.
If there is a constructor present in the subclass, it needs to first call
`super()` before using `this`. The `super` keyword can also be used to call
corresponding methods of super class.
class Cat {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Lion extends Cat {
speak() {
super.speak();
console.log(`${this.name} roars.`);
}
}
const l = new Lion("Fuzzy");
l.speak();
// Fuzzy makes a noise.
// Fuzzy roars.
### Evaluation order
When a `class` declaration or `class` expression is evaluated, its various
components are evaluated in the following order:
1. The `extends` clause, if present, is first evaluated. It must evaluate to a valid constructor function or `null`, or a `TypeError` is thrown.
2. The `constructor` method is extracted, substituted with a default implementation if `constructor` is not present. However, because the `constructor` definition is only a method definition, this step is not observable.
3. The class elements' property keys are evaluated in the order of declaration. If the property key is computed, the computed expression is evaluated, with the `this` value set to the `this` value surrounding the class (not the class itself). None of the property values are evaluated yet.
4. Methods and accessors are installed in the order of declaration. Instance methods and accessors are installed on the `prototype` property of the current class, and static methods and accessors are installed on the class itself. Private instance methods and accessors are saved to be installed on the instance directly later. This step is not observable.
5. The class is now initialized with the prototype specified by `extends` and implementation specified by `constructor`. For all steps above, if an evaluated expression tries to access the name of the class, a `ReferenceError` is thrown because the class is not initialized yet.
6. The class elements' values are evaluated in the order of declaration:
* For each instance field (public or private), its initializer expression is saved. The initializer is evaluated during instance creation, at the start of the constructor (for base classes) or immediately before the `super()` call returns (for derived classes).
* For each static field (public or private), its initializer is evaluated with `this` set to the class itself, and the property is created on the class.
* Static initialization blocks are evaluated with `this` set to the class itself.
7. The class is now fully initialized and can be used as a constructor function.
For how instances are created, see the `constructor` reference.
## Examples
### Binding this with instance and static methods
When a static or instance method is called without a value for `this`, such as
by assigning the method to a variable and then calling it, the `this` value
will be `undefined` inside the method. This behavior is the same even if the
`"use strict"` directive isn't present, because code within the `class` body
is always executed in strict mode.
class Animal {
speak() {
return this;
}
static eat() {
return this;
}
}
const obj = new Animal();
obj.speak(); // the Animal object
const speak = obj.speak;
speak(); // undefined
Animal.eat(); // class Animal
const eat = Animal.eat;
eat(); // undefined
If we rewrite the above using traditional function-based syntax in non–strict
mode, then `this` method calls are automatically bound to `globalThis`. In
strict mode, the value of `this` remains as `undefined`.
function Animal() {}
Animal.prototype.speak = function () {
return this;
};
Animal.eat = function () {
return this;
};
const obj = new Animal();
const speak = obj.speak;
speak(); // global object (in non–strict mode)
const eat = Animal.eat;
eat(); // global object (in non-strict mode)
## Specifications
## Browser compatibility
| Desktop | Mobile | Server
---|---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android | Deno | Node.js
`Classes` | 4942–49Strict mode is required. | 13 | 45 | 3629–36Strict mode is required. | 9 | 4942–49Strict mode is required. | 45 | 3629–36Strict mode is required. | 9 | 5.04.0–5.0Strict mode is required. | 4942–49Strict mode is required. | 1.0 | 6.0.0
`constructor` | 4942–49Strict mode is required. | 13 | 45 | 3629–36Strict mode is required. | 9 | 4942–49Strict mode is required. | 45 | 3629–36Strict mode is required. | 9 | 5.04.0–5.0Strict mode is required. | 4942–49Strict mode is required. | 1.0 | 6.0.0
`extends` | 4942–49Strict mode is required. | 13 | 45 | 3629–36Strict mode is required. | 9 | 4942–49Strict mode is required. | 45 | 3629–36Strict mode is required. | 9 | 5.04.0–5.0Strict mode is required. | 4942–49Strict mode is required. | 1.0 | 6.0.0
`private_class_fields` | 74 | 79 | 90 | 62 | 14.1 | 74 | 90 | 53 | 14.5 | 11.0 | 74 | 1.0 | 12.0.0
`private_class_fields_in` | 91 | 91 | 90 | 77 | 15 | 91 | 90 | 64 | 15 | 16.0 | 91 | 1.9 | 16.4.0
`private_class_methods` | 84 | 84 | 90 | 70 | 15 | 84 | 90 | 60 | 15 | 14.0 | 84 | 1.0 | 14.6.0
`public_class_fields` | 72 | 79 | 69 | 60 | 1614.1–16Parentheses in field initializers can lead to `ReferenceError`s. See bug 236843.14–14.1Doesn't support public static fields. See bug 194095. | 72 | 79 | 51 | 1614.5–16Parentheses in field initializers can lead to `ReferenceError`s. See bug 236843.14–14.5Doesn't support public static fields. See bug 194095. | 11.0 | 72 | 1.0 | 12.0.0
`static` | 4942–49Strict mode is required. | 13 | 45 | 3629–36Strict mode is required. | 9 | 4942–49Strict mode is required. | 45 | 3629–36Strict mode is required. | 9 | 5.04.0–5.0Strict mode is required. | 4942–49Strict mode is required. | 1.0 | 6.0.0
`static_class_fields` | 72 | 79 | 75 | 60 | 14.1 | 72 | 79 | 51 | 14.5 | 11.0 | 72 | 1.0 | 12.0.0
`static_initialization_blocks` | 94 | 94 | 93 | 80 | 16.4 | 94 | 93 | 66 | 16.4 | 17.0 | 94 | 1.14 | 16.11.0
## See also
* Using classes guide
* `class`
* `class` expression
* Functions
* ES6 In Depth: Classes on hacks.mozilla.org (2015)
# constructor
Baseline Widely available
This feature is well established and works across many devices and browser
versions. It’s been available across browsers since March 2016.
* Learn more
* See full compatibility
* Report feedback
The `constructor` method is a special method of a class for creating and
initializing an object instance of that class.
**Note:** This page introduces the `constructor` syntax. For the `constructor`
property present on all objects, see `Object.prototype.constructor`.
## Try it
class Polygon {
constructor() {
this.name = "Polygon";
}
}
const poly1 = new Polygon();
console.log(poly1.name);
// Expected output: "Polygon"
## Syntax
constructor() { /* … */ }
constructor(argument0) { /* … */ }
constructor(argument0, argument1) { /* … */ }
constructor(argument0, argument1, /* …, */ argumentN) { /* … */ }
There are some additional syntax restrictions:
* A class method called `constructor` cannot be a getter, setter, async, or generator.
* A class cannot have more than one `constructor` method.
## Description
A constructor enables you to provide any custom initialization that must be
done before any other methods can be called on an instantiated object.
class Person {
constructor(name) {
this.name = name;
}
introduce() {
console.log(`Hello, my name is ${this.name}`);
}
}
const otto = new Person("Otto");
otto.introduce(); // Hello, my name is Otto
If you don't provide your own constructor, then a default constructor will be
supplied for you. If your class is a base class, the default constructor is
empty:
constructor() {}
If your class is a derived class, the default constructor calls the parent
constructor, passing along any arguments that were provided:
constructor(...args) {
super(...args);
}
**Note:** The difference between an explicit constructor like the one above
and the default constructor is that the latter doesn't actually invoke the
array iterator through argument spreading.
That enables code like this to work:
class ValidationError extends Error {
printCustomerMessage() {
return `Validation failed :-( (details: ${this.message})`;
}
}
try {
throw new ValidationError("Not a valid phone number");
} catch (error) {
if (error instanceof ValidationError) {
console.log(error.name); // This is Error instead of ValidationError!
console.log(error.printCustomerMessage());
} else {
console.log("Unknown error", error);
throw error;
}
}
The `ValidationError` class doesn't need an explicit constructor, because it
doesn't need to do any custom initialization. The default constructor then
takes care of initializing the parent `Error` from the argument it is given.
However, if you provide your own constructor, and your class derives from some
parent class, then you must explicitly call the parent class constructor using
`super()`. For example:
class ValidationError extends Error {
constructor(message) {
super(message); // call parent class constructor
this.name = "ValidationError";
this.code = "42";
}
printCustomerMessage() {
return `Validation failed :-( (details: ${this.message}, code: ${this.code})`;
}
}
try {
throw new ValidationError("Not a valid phone number");
} catch (error) {
if (error instanceof ValidationError) {
console.log(error.name); // Now this is ValidationError!
console.log(error.printCustomerMessage());
} else {
console.log("Unknown error", error);
throw error;
}
}
Using `new` on a class goes through the following steps:
1. (If it's a derived class) The `constructor` body before the `super()` call is evaluated. This part should not access `this` because it's not yet initialized.
2. (If it's a derived class) The `super()` call is evaluated, which initializes the parent class through the same process.
3. The current class's fields are initialized.
4. The `constructor` body after the `super()` call (or the entire body, if it's a base class) is evaluated.
Within the `constructor` body, you can access the object being created through
`this` and access the class that is called with `new` through `new.target`.
Note that methods (including getters and setters) and the prototype chain are
already initialized on `this` before the `constructor` is executed, so you can
even access methods of the subclass from the constructor of the superclass.
However, if those methods use `this`, the `this` will not have been fully
initialized yet. This means reading public fields of the derived class will
result in `undefined`, while reading private fields will result in a
`TypeError`.
new (class C extends class B {
constructor() {
console.log(this.foo());
}
} {
#a = 1;
foo() {
return this.#a; // TypeError: Cannot read private member #a from an object whose class did not declare it
// It's not really because the class didn't declare it,
// but because the private field isn't initialized yet
// when the superclass constructor is running
}
})();
The `constructor` method may have a return value. While the base class may
return anything from its constructor, the derived class must return an object
or `undefined`, or a `TypeError` will be thrown.
class ParentClass {
constructor() {
return 1;
}
}
console.log(new ParentClass()); // ParentClass {}
// The return value is ignored because it's not an object
// This is consistent with function constructors
class ChildClass extends ParentClass {
constructor() {
return 1;
}
}
console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined
If the parent class constructor returns an object, that object will be used as
the `this` value on which class fields of the derived class will be defined.
This trick is called "return overriding", which allows a derived class's
fields (including private ones) to be defined on unrelated objects.
The `constructor` follows normal method syntax, so parameter default values,
rest parameters, etc. can all be used.
class Person {
constructor(name = "Anonymous") {
this.name = name;
}
introduce() {
console.log(`Hello, my name is ${this.name}`);
}
}
const person = new Person();
person.introduce(); // Hello, my name is Anonymous
The constructor must be a literal name. Computed properties cannot become
constructors.
class Foo {
// This is a computed property. It will not be picked up as a constructor.
["constructor"]() {
console.log("called");
this.a = 1;
}
}
const foo = new Foo(); // No log
console.log(foo); // Foo {}
foo.constructor(); // Logs "called"
console.log(foo); // Foo { a: 1 }
Async methods, generator methods, accessors, and class fields are forbidden
from being called `constructor`. Private names cannot be called
`#constructor`. Any member named `constructor` must be a plain method.
## Examples
### Using the constructor
This code snippet is taken from the classes sample (live demo).
class Square extends Polygon {
constructor(length) {
// Here, it calls the parent class' constructor with lengths
// provided for the Polygon's width and height
super(length, length);
// NOTE: In derived classes, `super()` must be called before you
// can use `this`. Leaving this out will cause a ReferenceError.
this.name = "Square";
}
get area() {
return this.height * this.width;
}
set area(value) {
this.height = value ** 0.5;
this.width = value ** 0.5;
}
}
### Calling super in a constructor bound to a different prototype
`super()` calls the constructor that's the prototype of the current class. If
you change the prototype of the current class itself, `super()` will call the
constructor that's the new prototype. Changing the prototype of the current
class's `prototype` property doesn't affect which constructor `super()` calls.
class Polygon {
constructor() {
this.name = "Polygon";
}
}
class Rectangle {
constructor() {
this.name = "Rectangle";
}
}
class Square extends Polygon {
constructor() {
super();
}
}
// Make Square extend Rectangle (which is a base class) instead of Polygon
Object.setPrototypeOf(Square, Rectangle);
const newInstance = new Square();
// newInstance is still an instance of Polygon, because we didn't
// change the prototype of Square.prototype, so the prototype chain
// of newInstance is still
// newInstance --> Square.prototype --> Polygon.prototype
console.log(newInstance instanceof Polygon); // true
console.log(newInstance instanceof Rectangle); // false
// However, because super() calls Rectangle as constructor, the name property
// of newInstance is initialized with the logic in Rectangle
console.log(newInstance.name); // Rectangle
## Specifications
## Browser compatibility
| Desktop | Mobile | Server
---|---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android | Deno | Node.js
`constructor` | 4942–49Strict mode is required. | 13 | 45 | 3629–36Strict mode is required. | 9 | 4942–49Strict mode is required. | 45 | 3629–36Strict mode is required. | 9 | 5.04.0–5.0Strict mode is required. | 4942–49Strict mode is required. | 1.0 | 6.0.0
## See also
* Using classes guide
* Classes
* Static initialization blocks
* `class`
* `super()`
* `Object.prototype.constructor`
# extends
Baseline Widely available
This feature is well established and works across many devices and browser
versions. It’s been available across browsers since March 2016.
* Learn more
* See full compatibility
* Report feedback
The `extends` keyword is used in class declarations or class expressions to
create a class that is a child of another class.
## Try it
class DateFormatter extends Date {
getFormattedDate() {
const months = [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
];
return `${this.getDate()}-${months[this.getMonth()]}-${this.getFullYear()}`;
}
}
console.log(new DateFormatter("August 19, 1975 23:15:30").getFormattedDate());
// Expected output: "19-Aug-1975"
## Syntax
class ChildClass extends ParentClass { /* … */ }
`ParentClass`
An expression that evaluates to a constructor function (including a class) or
`null`.
## Description
The `extends` keyword can be used to subclass custom classes as well as built-
in objects.
Any constructor that can be called with `new` and has the `prototype` property
can be the candidate for the parent class. The two conditions must both hold —
for example, bound functions and `Proxy` can be constructed, but they don't
have a `prototype` property, so they cannot be subclassed.
function OldStyleClass() {
this.someProperty = 1;
}
OldStyleClass.prototype.someMethod = function () {};
class ChildClass extends OldStyleClass {}
class ModernClass {
someProperty = 1;
someMethod() {}
}
class AnotherChildClass extends ModernClass {}
The `prototype` property of the `ParentClass` must be an `Object` or `null`,
but you would rarely worry about this in practice, because a non-object
`prototype` doesn't behave as it should anyway. (It's ignored by the `new`
operator.)
function ParentClass() {}
ParentClass.prototype = 3;
class ChildClass extends ParentClass {}
// Uncaught TypeError: Class extends value does not have valid prototype property 3
console.log(Object.getPrototypeOf(new ParentClass()));
// [Object: null prototype] {}
// Not actually a number!
`extends` sets the prototype for both `ChildClass` and `ChildClass.prototype`.
| Prototype of `ChildClass` | Prototype of `ChildClass.prototype`
---|---|---
`extends` clause absent | `Function.prototype` | `Object.prototype`
`extends null` | `Function.prototype` | `null`
`extends ParentClass` | `ParentClass` | `ParentClass.prototype`
class ParentClass {}
class ChildClass extends ParentClass {}
// Allows inheritance of static properties
Object.getPrototypeOf(ChildClass) === ParentClass;
// Allows inheritance of instance properties
Object.getPrototypeOf(ChildClass.prototype) === ParentClass.prototype;
The right-hand side of `extends` does not have to be an identifier. You can
use any expression that evaluates to a constructor. This is often useful to
create mixins. The `this` value in the `extends` expression is the `this`
surrounding the class definition, and referring to the class's name is a
`ReferenceError` because the class is not initialized yet. `await` and `yield`
work as expected in this expression.
class SomeClass extends class {
constructor() {
console.log("Base class");
}
} {
constructor() {
super();
console.log("Derived class");
}
}
new SomeClass();
// Base class
// Derived class
While the base class may return anything from its constructor, the derived
class must return an object or `undefined`, or a `TypeError` will be thrown.
class ParentClass {
constructor() {
return 1;
}
}
console.log(new ParentClass()); // ParentClass {}
// The return value is ignored because it's not an object
// This is consistent with function constructors
class ChildClass extends ParentClass {
constructor() {
super();
return 1;
}
}
console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined
If the parent class constructor returns an object, that object will be used as
the `this` value for the derived class when further initializing class fields.
This trick is called "return overriding", which allows a derived class's
fields (including private ones) to be defined on unrelated objects.
### Subclassing built-ins
**Warning:** The standard committee now holds the position that the built-in
subclassing mechanism in previous spec versions is over-engineered and causes
non-negligible performance and security impacts. New built-in methods consider
less about subclasses, and engine implementers are investigating whether to
remove certain subclassing mechanisms. Consider using composition instead of
inheritance when enhancing built-ins.
Here are some things you may expect when extending a class:
* When calling a static factory method (like `Promise.resolve()` or `Array.from()`) on a subclass, the returned instance is always an instance of the subclass.
* When calling an instance method that returns a new instance (like `Promise.prototype.then()` or `Array.prototype.map()`) on a subclass, the returned instance is always an instance of the subclass.
* Instance methods try to delegate to a minimal set of primitive methods where possible. For example, for a subclass of `Promise`, overriding `then()` automatically causes the behavior of `catch()` to change; or for a subclass of `Map`, overriding `set()` automatically causes the behavior of the `Map()` constructor to change.
However, the above expectations take non-trivial efforts to implement
properly.
* The first one requires the static method to read the value of `this` to get the constructor for constructing the returned instance. This means `[p1, p2, p3].map(Promise.resolve)` throws an error because the `this` inside `Promise.resolve` is `undefined`. A way to fix this is to fall back to the base class if `this` is not a constructor, like `Array.from()` does, but that still means the base class is special-cased.
* The second one requires the instance method to read `this.constructor` to get the constructor function. However, `new this.constructor()` may break legacy code, because the `constructor` property is both writable and configurable and is not protected in any way. Therefore, many copying built-in methods use the constructor's `[Symbol.species]` property instead (which by default just returns `this`, the constructor itself). However, `[Symbol.species]` allows running arbitrary code and creating instances of arbitrary type, which poses a security concern and greatly complicates subclassing semantics.
* The third one leads to visible invocations of custom code, which makes a lot of optimizations harder to implement. For example, if the `Map()` constructor is called with an iterable of _x_ elements, then it must visibly invoke the `set()` method _x_ times, instead of just copying the elements into the internal storage.
These problems are not unique to built-in classes. For your own classes, you
will likely have to make the same decisions. However, for built-in classes,
optimizability and security are a much bigger concern. New built-in methods
always construct the base class and call as few custom methods as possible. If
you want to subclass built-ins while achieving the above expectations, you
need to override all methods that have the default behavior baked into them.
Any addition of new methods on the base class may also break the semantics of
your subclass because they are inherited by default. Therefore, a better way
to extend built-ins is to use _composition_.
### Extending null
`extends null` was designed to allow easy creation of objects that do not
inherit from `Object.prototype`. However, due to unsettled decisions about
whether `super()` should be called within the constructor, it's not possible
to construct such a class in practice using any constructor implementation
that doesn't return an object. The TC39 committee is working on re-enabling
this feature.
new (class extends null {})();
// TypeError: Super constructor null of anonymous class is not a constructor
new (class extends null {
constructor() {}
})();
// ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
new (class extends null {
constructor() {
super();
}
})();
// TypeError: Super constructor null of anonymous class is not a constructor
Instead, you need to explicitly return an instance from the constructor.
class NullClass extends null {
constructor() {
// Using new.target allows derived classes to
// have the correct prototype chain
return Object.create(new.target.prototype);
}
}
const proto = Object.getPrototypeOf;
console.log(proto(proto(new NullClass()))); // null
## Examples
### Using extends
The first example creates a class called `Square` from a class called
`Polygon`. This example is extracted from this live demo (source).
class Square extends Polygon {
constructor(length) {
// Here, it calls the parent class' constructor with lengths
// provided for the Polygon's width and height
super(length, length);
// Note: In derived classes, super() must be called before you
// can use 'this'. Leaving this out will cause a reference error.
this.name = "Square";
}
get area() {
return this.height * this.width;
}
}
### Extending plain objects
Classes cannot extend regular (non-constructible) objects. If you want to
inherit from a regular object by making all properties of this object
available on inherited instances, you can instead use
`Object.setPrototypeOf()`:
const Animal = {
speak() {
console.log(`${this.name} makes a noise.`);
},
};
class Dog {
constructor(name) {
this.name = name;
}
}
Object.setPrototypeOf(Dog.prototype, Animal);
const d = new Dog("Mitzie");
d.speak(); // Mitzie makes a noise.
### Extending built-in objects
This example extends the built-in `Date` object. This example is extracted
from this live demo (source).
class MyDate extends Date {
getFormattedDate() {
const months = [
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
];
return `${this.getDate()}-${months[this.getMonth()]}-${this.getFullYear()}`;
}
}
### Extending `Object`
All JavaScript objects inherit from `Object.prototype` by default, so writing
`extends Object` at first glance seems redundant. The only difference from not
writing `extends` at all is that the constructor itself inherits static
methods from `Object`, such as `Object.keys()`. However, because no `Object`
static method uses the `this` value, there's still no value in inheriting
these static methods.
The `Object()` constructor special-cases the subclassing scenario. If it's
implicitly called via `super()`, it always initializes a new object with
`new.target.prototype` as its prototype. Any value passed to `super()` is
ignored.
class C extends Object {
constructor(v) {
super(v);
}
}
console.log(new C(1) instanceof Number); // false
console.log(C.keys({ a: 1, b: 2 })); // [ 'a', 'b' ]
Compare this behavior with a custom wrapper that does not special-case
subclassing:
function MyObject(v) {
return new Object(v);
}
class D extends MyObject {
constructor(v) {
super(v);
}
}
console.log(new D(1) instanceof Number); // true
### Species
You might want to return `Array` objects in your derived array class
`MyArray`. The species pattern lets you override default constructors.
For example, when using methods such as `Array.prototype.map()` that return
the default constructor, you want these methods to return a parent `Array`
object, instead of the `MyArray` object. The `Symbol.species` symbol lets you
do this:
class MyArray extends Array {
// Overwrite species to the parent Array constructor
static get [Symbol.species]() {
return Array;
}
}
const a = new MyArray(1, 2, 3);
const mapped = a.map((x) => x * x);
console.log(mapped instanceof MyArray); // false
console.log(mapped instanceof Array); // true
This behavior is implemented by many built-in copying methods. For caveats of
this feature, see the subclassing built-ins discussion.
### Mix-ins
Abstract subclasses or _mix-ins_ are templates for classes. A class can only
have a single superclass, so multiple inheritance from tooling classes, for
example, is not possible. The functionality must be provided by the
superclass.
A function with a superclass as input and a subclass extending that superclass
as output can be used to implement mix-ins:
const calculatorMixin = (Base) =>
class extends Base {
calc() {}
};
const randomizerMixin = (Base) =>
class extends Base {
randomize() {}
};
A class that uses these mix-ins can then be written like this:
class Foo {}
class Bar extends calculatorMixin(randomizerMixin(Foo)) {}
### Avoiding inheritance
Inheritance is a very strong coupling relationship in object-oriented
programming. It means all behaviors of the base class are inherited by the
subclass by default, which may not always be what you want. For example,
consider the implementation of a `ReadOnlyMap`:
class ReadOnlyMap extends Map {
set() {
throw new TypeError("A read-only map must be set at construction time.");
}
}
It turns out that `ReadOnlyMap` is not constructible, because the `Map()`
constructor calls the instance's `set()` method.
const m = new ReadOnlyMap([["a", 1]]); // TypeError: A read-only map must be set at construction time.
We may get around this by using a private flag to indicate whether the
instance is being constructed. However, a more significant problem with this
design is that it breaks the Liskov substitution principle, which states that
a subclass should be substitutable for its superclass. If a function expects a
`Map` object, it should be able to use a `ReadOnlyMap` object as well, which
will break here.
Inheritance often leads to the circle-ellipse problem, because neither type
perfectly entails the behavior of the other, although they share a lot of
common traits. In general, unless there's a very good reason to use
inheritance, it's better to use composition instead. Composition means that a
class has a reference to an object of another class, and only uses that object
as an implementation detail.
class ReadOnlyMap {
#data;
constructor(values) {
this.#data = new Map(values);
}
get(key) {
return this.#data.get(key);
}
has(key) {
return this.#data.has(key);
}
get size() {
return this.#data.size;
}
*keys() {
yield* this.#data.keys();
}
*values() {
yield* this.#data.values();
}
*entries() {
yield* this.#data.entries();
}
*[Symbol.iterator]() {
yield* this.#data[Symbol.iterator]();
}
}
In this case, the `ReadOnlyMap` class is not a subclass of `Map`, but it still
implements most of the same methods. This means more code duplication, but it
also means that the `ReadOnlyMap` class is not strongly coupled to the `Map`
class, and does not easily break if the `Map` class is changed, avoiding the
semantic issues of built-in subclassing. For example, if the `Map` class adds
a new utility method (such as `getOrInsert()`) that does not call `set()`, it
would cause the `ReadOnlyMap` class to no longer be read-only unless the
latter is updated accordingly to override `getOrInsert()` as well. Moreover,
`ReadOnlyMap` objects do not have the `set` method at all, which is more
accurate than throwing an error at runtime.
## Specifications
## Browser compatibility
| Desktop | Mobile | Server
---|---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android | Deno | Node.js
`extends` | 4942–49Strict mode is required. | 13 | 45 | 3629–36Strict mode is required. | 9 | 4942–49Strict mode is required. | 45 | 3629–36Strict mode is required. | 9 | 5.04.0–5.0Strict mode is required. | 4942–49Strict mode is required. | 1.0 | 6.0.0
## See also
* Using classes guide
* Classes
* `constructor`
* `class`
* `super`
# Private properties
**Private properties** are counterparts of the regular class properties which
are public, including class fields, class methods, etc. Private properties get
created by using a hash `#` prefix and cannot be legally referenced outside of
the class. The privacy encapsulation of these class properties is enforced by
JavaScript itself. The only way to access a private property is via dot
notation, and you can only do so within the class that defines the private
property.
Private properties were not native to the language before this syntax existed.
In prototypal inheritance, its behavior may be emulated with `WeakMap` objects
or closures, but they can't compare to the `#` syntax in terms of ergonomics.
## Syntax
class ClassWithPrivate {
#privateField;
#privateFieldWithInitializer = 42;
#privateMethod() {
// …
}
static #privateStaticField;
static #privateStaticFieldWithInitializer = 42;
static #privateStaticMethod() {
// …
}
}
There are some additional syntax restrictions:
* All private identifiers declared within a class must be unique. The namespace is shared between static and instance properties. The only exception is when the two declarations define a getter-setter pair.
* The private identifier cannot be `#constructor`.
## Description
Most class properties have their private counterparts:
* Private fields
* Private methods
* Private static fields
* Private static methods
* Private getters
* Private setters
* Private static getters
* Private static setters
These features are collectively called _private properties_. However,
constructors cannot be private in JavaScript. To prevent classes from being
constructed outside of the class, you have to use a private flag.
Private properties are declared with **# names** (pronounced "hash names"),
which are identifiers prefixed with `#`. The hash prefix is an inherent part
of the property name — you can draw relationship with the old underscore
prefix convention `_privateField` — but it's not an ordinary string property,
so you can't dynamically access it with the bracket notation.
It is a syntax error to refer to `#` names from outside of the class. It is
also a syntax error to refer to private properties that were not declared in
the class body, or to attempt to remove declared properties with `delete`.
class ClassWithPrivateField {
#privateField;
constructor() {
delete this.#privateField; // Syntax error
this.#undeclaredField = 42; // Syntax error
}
}
const instance = new ClassWithPrivateField();
instance.#privateField; // Syntax error
JavaScript, being a dynamic language, is able to perform this compile-time
check because of the special hash identifier syntax, making it different from
normal properties on the syntax level.
**Note:** Code run in the Chrome console can access private properties outside
the class. This is a DevTools-only relaxation of the JavaScript syntax
restriction.
If you access a private property from an object that doesn't have the
property, a `TypeError` is thrown, instead of returning `undefined` as normal
properties do.
class C {
#x;
static getX(obj) {
return obj.#x;
}
}
console.log(C.getX(new C())); // undefined
console.log(C.getX({})); // TypeError: Cannot read private member #x from an object whose class did not declare it
This example also illustrates that you can access private properties within
static functions too, and on externally defined instances of the class.
You can use the `in` operator to check whether an externally defined object
possesses a private property. This will return `true` if the private field or
method exists, and `false` otherwise.
class C {
#x;
constructor(x) {
this.#x = x;
}
static getX(obj) {
if (#x in obj) return obj.#x;
return "obj must be an instance of C";
}
}
console.log(C.getX(new C("foo"))); // "foo"
console.log(C.getX(new C(0.196))); // 0.196
console.log(C.getX(new C(new Date()))); // the current date and time
console.log(C.getX({})); // "obj must be an instance of C"
Note a corollary of private names being always pre-declared and non-deletable:
if you found that an object possesses one private property of the current
class (either from a `try...catch` or an `in` check), it must possess all
other private properties. An object possessing the private properties of a
class generally means it was constructed by that class (although not always).
Private properties are not part of the prototypical inheritance model since
they can only be accessed within the current class's body and aren't inherited
by subclasses. Private properties with the same name within different classes
are entirely different and do not interoperate with each other. See them as
external metadata attached to each instance, managed by the class. For this
reason, `structuredClone()` does not clone private properties, and
`Object.freeze()` and `Object.seal()` have no effect on private properties.
For more information on how and when private fields are initialized, see
public class fields.
## Examples
### Private fields
Private fields include private instance fields and private static fields.
Private fields are only accessible from inside the class declaration.
#### Private instance fields
Like their public counterparts, private instance fields:
* are added before the constructor runs in a base class, or immediately after `super()` is invoked in a subclass, and
* are only available on instances of the class.
class ClassWithPrivateField {
#privateField;
constructor() {
this.#privateField = 42;
}
}
class Subclass extends ClassWithPrivateField {
#subPrivateField;
constructor() {
super();
this.#subPrivateField = 23;
}
}
new Subclass(); // In some dev tools, it shows Subclass {#privateField: 42, #subPrivateField: 23}
**Note:** `#privateField` from the `ClassWithPrivateField` base class is
private to `ClassWithPrivateField` and is not accessible from the derived
`Subclass`.
#### Returning overriding object
A class's constructor can return a different object, which will be used as the
new `this` for the derived class constructor. The derived class may then
define private fields on that returned object — meaning it is possible to
"stamp" private fields onto unrelated objects.
class Stamper extends class {
// A base class whose constructor returns the object it's given
constructor(obj) {
return obj;
}
} {
// This declaration will "stamp" the private field onto the object
// returned by the base class constructor
#stamp = 42;
static getStamp(obj) {
return obj.#stamp;
}
}
const obj = {};
new Stamper(obj);
// `Stamper` calls `Base`, which returns `obj`, so `obj` is
// now the `this` value. `Stamper` then defines `#stamp` on `obj`
console.log(obj); // In some dev tools, it shows {#stamp: 42}
console.log(Stamper.getStamp(obj)); // 42
console.log(obj instanceof Stamper); // false
// You cannot stamp private properties twice
new Stamper(obj); // Error: Initializing an object twice is an error with private fields
**Warning:** This is a potentially very confusing thing to do. You are
generally advised to avoid returning anything from the constructor —
especially something unrelated to `this`.
#### Private static fields
Like their public counterparts, private static fields:
* are added to the class constructor at class evaluation time, and
* are only available on the class itself.
class ClassWithPrivateStaticField {
static #privateStaticField = 42;
static publicStaticMethod() {
return ClassWithPrivateStaticField.#privateStaticField;
}
}
console.log(ClassWithPrivateStaticField.publicStaticMethod()); // 42
There is a restriction on private static fields: only the class which defines
the private static field can access the field. This can lead to unexpected
behavior when using `this`. In the following example, `this` refers to the
`Subclass` class (not the `ClassWithPrivateStaticField` class) when we try to
call `Subclass.publicStaticMethod()`, and so causes a `TypeError`.
class ClassWithPrivateStaticField {
static #privateStaticField = 42;
static publicStaticMethod() {
return this.#privateStaticField;
}
}
class Subclass extends ClassWithPrivateStaticField {}
Subclass.publicStaticMethod(); // TypeError: Cannot read private member #privateStaticField from an object whose class did not declare it
This is the same if you call the method with `super`, because `super` methods
are not called with the super class as `this`.
class ClassWithPrivateStaticField {
static #privateStaticField = 42;
static publicStaticMethod() {
// When invoked through super, `this` still refers to Subclass
return this.#privateStaticField;
}
}
class Subclass extends ClassWithPrivateStaticField {
static callSuperMethod() {
return super.publicStaticMethod();
}
}
Subclass.callSuperMethod(); // TypeError: Cannot read private member #privateStaticField from an object whose class did not declare it
You are advised to always access private static fields through the class name,
not through `this`, so inheritance doesn't break the method.
### Private methods
Private methods include private instance methods and private static methods.
Private methods are only accessible from inside the class declaration.
#### Private instance methods
Unlike their public counterparts, private instance methods:
* are installed immediately before the instance fields are installed, and
* are only available on instances of the class, not on its `.prototype` property.
class ClassWithPrivateMethod {
#privateMethod() {
return 42;
}
publicMethod() {
return this.#privateMethod();
}
}
const instance = new ClassWithPrivateMethod();
console.log(instance.publicMethod()); // 42
Private instance methods may be generator, async, or async generator
functions. Private getters and setters are also possible, and follow the same
syntax requirements as their public getter and setter counterparts.
class ClassWithPrivateAccessor {
#message;
get #decoratedMessage() {
return `🎬${this.#message}🛑`;
}
set #decoratedMessage(msg) {
this.#message = msg;
}
constructor() {
this.#decoratedMessage = "hello world";
console.log(this.#decoratedMessage);
}
}
new ClassWithPrivateAccessor(); // 🎬hello world🛑
Unlike public methods, private methods are not accessible on the `.prototype`
property of their class.
class C {
#method() {}
static getMethod(x) {
return x.#method;
}
}
console.log(C.getMethod(new C())); // [Function: #method]
console.log(C.getMethod(C.prototype)); // TypeError: Receiver must be an instance of class C
#### Private static methods
Like their public counterparts, private static methods:
* are added to the class constructor at class evaluation time, and
* are only available on the class itself.
class ClassWithPrivateStaticMethod {
static #privateStaticMethod() {
return 42;
}
static publicStaticMethod() {
return ClassWithPrivateStaticMethod.#privateStaticMethod();
}
}
console.log(ClassWithPrivateStaticMethod.publicStaticMethod()); // 42
Private static methods may be generator, async, and async generator functions.
The same restriction previously mentioned for private static fields holds for
private static methods, and similarly can lead to unexpected behavior when
using `this`. In the following example, when we try to call
`Subclass.publicStaticMethod()`, `this` refers to the `Subclass` class (not
the `ClassWithPrivateStaticMethod` class) and so causes a `TypeError`.
class ClassWithPrivateStaticMethod {
static #privateStaticMethod() {
return 42;
}
static publicStaticMethod() {
return this.#privateStaticMethod();
}
}
class Subclass extends ClassWithPrivateStaticMethod {}
console.log(Subclass.publicStaticMethod()); // TypeError: Cannot read private member #privateStaticMethod from an object whose class did not declare it
### Simulating private constructors
Many other languages include the capability to mark a constructor as private,
which prevents the class from being instantiated outside of the class itself —
you can only use static factory methods that create instances, or not be able
to create instances at all. JavaScript does not have a native way to do this,
but it can be accomplished by using a private static flag.
class PrivateConstructor {
static #isInternalConstructing = false;
constructor() {
if (!PrivateConstructor.#isInternalConstructing) {
throw new TypeError("PrivateConstructor is not constructable");
}
PrivateConstructor.#isInternalConstructing = false;
// More initialization logic
}
static create() {
PrivateConstructor.#isInternalConstructing = true;
const instance = new PrivateConstructor();
return instance;
}
}
new PrivateConstructor(); // TypeError: PrivateConstructor is not constructable
PrivateConstructor.create(); // PrivateConstructor {}
## Specifications
## Browser compatibility
| Desktop | Mobile | Server
---|---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android | Deno | Node.js
`Private_properties` | 84 | 84 | 90 | 70 | 15 | 84 | 90 | 60 | 15 | 14.0 | 84 | 1.0 | 14.6.0
| Desktop | Mobile | Server
---|---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android | Deno | Node.js
`Private_properties` | 91 | 91 | 90 | 77 | 15 | 91 | 90 | 64 | 15 | 16.0 | 91 | 1.9 | 16.4.0
| Desktop | Mobile | Server
---|---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android | Deno | Node.js
`Private_properties` | 74 | 79 | 90 | 62 | 14.1 | 74 | 90 | 53 | 14.5 | 11.0 | 74 | 1.0 | 12.0.0
### javascript.classes.private_class_fields
### javascript.classes.private_class_fields_in
### javascript.classes.private_class_methods
## See also
* Using classes guide
* Classes
* Public class fields
* `class`
* Private Syntax FAQ in the TC39 class-fields proposal
* The semantics of all JS class elements by Shu-yu Guo (2018)
* Public and private class fields on v8.dev (2018)
# Public class fields
Baseline Widely available
This feature is well established and works across many devices and browser
versions. It’s been available across browsers since September 2022.
* Learn more
* See full compatibility
* Report feedback
**Public fields** are writable, enumerable, and configurable properties
defined on each class instance or class constructor.
## Syntax
class ClassWithField {
instanceField;
instanceFieldWithInitializer = "instance field";
static staticField;
static staticFieldWithInitializer = "static field";
}
There are some additional syntax restrictions:
* The name of a static property (field or method) cannot be `prototype`.
* The name of a class field (static or instance) cannot be `constructor`.
## Description
This page introduces public instance fields in detail.
* For public static fields, see `static`.
* For private fields, see private properties.
* For public methods, see method definitions.
* For public accessors, see getter and setter.
Public instance fields exist on every created instance of a class. By
declaring a public field, you can ensure the field is always present, and the
class definition is more self-documenting.
Public instance fields are added to the instance either at construction time
in the base class (before the constructor body runs), or just after `super()`
returns in a subclass. Fields without initializers are initialized to
`undefined`. Like properties, field names may be computed.
const PREFIX = "prefix";
class ClassWithField {
field;
fieldWithInitializer = "instance field";
[`${PREFIX}Field`] = "prefixed field";
}
const instance = new ClassWithField();
console.log(Object.hasOwn(instance, "field")); // true
console.log(instance.field); // undefined
console.log(instance.fieldWithInitializer); // "instance field"
console.log(instance.prefixField); // "prefixed field"
Computed field names are only evaluated once, at class definition time. This
means that each class always has a fixed set of field names, and two instances
cannot have different field names via computed names. The `this` value in the
computed expression is the `this` surrounding the class definition, and
referring to the class's name is a `ReferenceError` because the class is not
initialized yet. `await` and `yield` work as expected in this expression.
class C {
[Math.random()] = 1;
}
console.log(new C());
console.log(new C());
// Both instances have the same field name
In the field initializer, `this` refers to the class instance under
construction, and `super` refers to the `prototype` property of the base
class, which contains the base class's instance methods, but not its instance
fields.
class Base {
baseField = "base field";
anotherBaseField = this.baseField;
baseMethod() {
return "base method output";
}
}
class Derived extends Base {
subField = super.baseMethod();
}
const base = new Base();
const sub = new Derived();
console.log(base.anotherBaseField); // "base field"
console.log(sub.subField); // "base method output"
The field initializer expression is evaluated each time a new instance is
created. (Because the `this` value is different for each instance, the
initializer expression can access instance-specific properties.)
class C {
obj = {};
}
const instance1 = new C();
const instance2 = new C();
console.log(instance1.obj === instance2.obj); // false
The expression is evaluated synchronously. You cannot use `await` or `yield`
in the initializer expression. (Think of the initializer expression as being
implicitly wrapped in a function.)
Because instance fields of a class are added before the respective constructor
runs, you can access the fields' values within the constructor. However,
because instance fields of a derived class are defined after `super()`
returns, the base class's constructor does not have access to the derived
class's fields.
class Base {
constructor() {
console.log("Base constructor:", this.field);
}
}
class Derived extends Base {
field = 1;
constructor() {
super();
console.log("Derived constructor:", this.field);
this.field = 2;
}
}
const instance = new Derived();
// Base constructor: undefined
// Derived constructor: 1
console.log(instance.field); // 2
Fields are added one-by-one. Field initializers can refer to field values
above it, but not below it. All instance and static methods are added
beforehand and can be accessed, although calling them may not behave as
expected if they refer to fields below the one being initialized.
class C {
a = 1;
b = this.c;
c = this.a + 1;
d = this.c + 1;
}
const instance = new C();
console.log(instance.d); // 3
console.log(instance.b); // undefined
**Note:** This is more important with private fields, because accessing a non-
initialized private field throws a `TypeError`, even if the private field is
declared below. (If the private field is not declared, it would be an early
`SyntaxError`.)
Because class fields are added using the `[[DefineOwnProperty]]` semantic
(which is essentially `Object.defineProperty()`), field declarations in
derived classes do not invoke setters in the base class. This behavior differs
from using `this.field = …` in the constructor.
class Base {
set field(val) {
console.log(val);
}
}
class DerivedWithField extends Base {
field = 1;
}
const instance = new DerivedWithField(); // No log
class DerivedWithConstructor extends Base {
constructor() {
super();
this.field = 1;
}
}
const instance2 = new DerivedWithConstructor(); // Logs 1
**Note:** Before the class fields specification was finalized with the
`[[DefineOwnProperty]]` semantic, most transpilers, including Babel and tsc,
transformed class fields to the `DerivedWithConstructor` form, which has
caused subtle bugs after class fields were standardized.
## Examples
### Using class fields
Class fields cannot depend on arguments of the constructor, so field
initializers usually evaluate to the same value for each instance (unless the
same expression can evaluate to different values each time, such as
`Math.random()` or object initializers).
class Person {
name = nameArg; // nameArg is out of scope of the constructor
constructor(nameArg) {}
}
class Person {
// All instances of Person will have the same name
name = "Dragomir";
}
However, even declaring an empty class field is beneficial, because it
indicates the existence of the field, which allows type checkers as well as
human readers to statically analyze the shape of the class.
class Person {
name;
age;
constructor(name, age) {
this.name = name;
this.age = age;
}
}
The code above seems repetitive, but consider the case where `this` is
dynamically mutated: the explicit field declaration makes it clear which
fields will definitely be present on the instance.
class Person {
name;
age;
constructor(properties) {
Object.assign(this, properties);
}
}
Because initializers are evaluated after the base class has executed, you can
access properties created by the base class constructor.
class Person {
name;
age;
constructor(name, age) {
this.name = name;
this.age = age;
}
}
class Professor extends Person {
name = `Professor ${this.name}`;
}
console.log(new Professor("Radev", 54).name); // "Professor Radev"
## Specifications
## Browser compatibility
| Desktop | Mobile | Server
---|---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android | Deno | Node.js
`Public_class_fields` | 72 | 79 | 69 | 60 | 1614.1–16Parentheses in field initializers can lead to `ReferenceError`s. See bug 236843.14–14.1Doesn't support public static fields. See bug 194095. | 72 | 79 | 51 | 1614.5–16Parentheses in field initializers can lead to `ReferenceError`s. See bug 236843.14–14.5Doesn't support public static fields. See bug 194095. | 11.0 | 72 | 1.0 | 12.0.0
## See also
* Using classes guide
* Classes
* Private properties
* `class`
* The semantics of all JS class elements by Shu-yu Guo (2018)
* Public and private class fields on v8.dev (2018)
# static
Baseline Widely available
This feature is well established and works across many devices and browser
versions. It’s been available across browsers since March 2016.
* Learn more
* See full compatibility
* Report feedback
The `static` keyword defines a static method or field for a class, or a static
initialization block (see the link for more information about this usage).
Static properties cannot be directly accessed on instances of the class.
Instead, they're accessed on the class itself.
Static methods are often utility functions, such as functions to create or
clone objects, whereas static properties are useful for caches, fixed-
configuration, or any other data you don't need to be replicated across
instances.
**Note:** In the context of classes, MDN Web Docs content uses the terms
properties and fields interchangeably.
## Try it
class ClassWithStaticMethod {
static staticProperty = "someValue";
static staticMethod() {
return "static method has been called.";
}
static {
console.log("Class static initialization block called");
}
}
console.log(ClassWithStaticMethod.staticProperty);
// Expected output: "someValue"
console.log(ClassWithStaticMethod.staticMethod());
// Expected output: "static method has been called."
## Syntax
class ClassWithStatic {
static staticField;
static staticFieldWithInitializer = value;
static staticMethod() {
// …
}
}
There are some additional syntax restrictions:
* The name of a static property (field or method) cannot be `prototype`.
* The name of a class field (static or instance) cannot be `constructor`.
## Description
This page introduces public static properties of classes, which include static
methods, static accessors, and static fields.
* For private static features, see private properties.
* For instance features, see methods definitions, getter, setter, and public class fields.
Public static features are declared using the `static` keyword. They are added
to the class constructor at the time of class evaluation using the
`[[DefineOwnProperty]]` semantic (which is essentially
`Object.defineProperty()`). They are accessed again from the class
constructor.
Static methods are often utility functions, such as functions to create or
clone instances. Public static fields are useful when you want a field to
exist only once per class, not on every class instance you create. This is
useful for caches, fixed-configuration, or any other data you don't need to be
replicated across instances.
Static field names can be computed. The `this` value in the computed
expression is the `this` surrounding the class definition, and referring to
the class's name is a `ReferenceError` because the class is not initialized
yet. `await` and `yield` work as expected in this expression.
Static fields can have an initializer. Static fields without initializers are
initialized to `undefined`. Public static fields are not reinitialized on
subclasses, but can be accessed via the prototype chain.
class ClassWithStaticField {
static staticField;
static staticFieldWithInitializer = "static field";
}
class SubclassWithStaticField extends ClassWithStaticField {
static subStaticField = "subclass field";
}
console.log(Object.hasOwn(ClassWithStaticField, "staticField")); // true
console.log(ClassWithStaticField.staticField); // undefined
console.log(ClassWithStaticField.staticFieldWithInitializer); // "static field"
console.log(SubclassWithStaticField.staticFieldWithInitializer); // "static field"
console.log(SubclassWithStaticField.subStaticField); // "subclass field"
In the field initializer, `this` refers to the current class (which you can
also access through its name), and `super` refers to the base class
constructor.
class ClassWithStaticField {
static baseStaticField = "base static field";
static anotherBaseStaticField = this.baseStaticField;
static baseStaticMethod() {
return "base static method output";
}
}
class SubClassWithStaticField extends ClassWithStaticField {
static subStaticField = super.baseStaticMethod();
}
console.log(ClassWithStaticField.anotherBaseStaticField); // "base static field"
console.log(SubClassWithStaticField.subStaticField); // "base static method output"
The expression is evaluated synchronously. You cannot use `await` or `yield`
in the initializer expression. (Think of the initializer expression as being
implicitly wrapped in a function.)
Static field initializers and static initialization blocks are evaluated one-
by-one. Field initializers can refer to field values above it, but not below
it. All static methods are added beforehand and can be accessed, although
calling them may not behave as expected if they refer to fields below the one
being initialized.
**Note:** This is more important with private static fields, because accessing
a non-initialized private field throws a `TypeError`, even if the private
field is declared below. (If the private field is not declared, it would be an
early `SyntaxError`.)
## Examples
### Using static members in classes
The following example demonstrates several things:
1. How a static member (method or property) is defined on a class.
2. That a class with a static member can be sub-classed.
3. How a static member can and cannot be called.
class Triple {
static customName = "Tripler";
static description = "I triple any number you provide";
static calculate(n = 1) {
return n * 3;
}
}
class SquaredTriple extends Triple {
static longDescription;
static description = "I square the triple of any number you provide";
static calculate(n) {
return super.calculate(n) * super.calculate(n);
}
}
console.log(Triple.description); // 'I triple any number you provide'
console.log(Triple.calculate()); // 3
console.log(Triple.calculate(6)); // 18
const tp = new Triple();
console.log(SquaredTriple.calculate(3)); // 81 (not affected by parent's instantiation)
console.log(SquaredTriple.description); // 'I square the triple of any number you provide'
console.log(SquaredTriple.longDescription); // undefined
console.log(SquaredTriple.customName); // 'Tripler'
// This throws because calculate() is a static member, not an instance member.
console.log(tp.calculate()); // 'tp.calculate is not a function'
### Calling static members from another static method
In order to call a static method or property within another static method of
the same class, you can use the `this` keyword.
class StaticMethodCall {
static staticProperty = "static property";
static staticMethod() {
return `Static method and ${this.staticProperty} has been called`;
}
static anotherStaticMethod() {
return `${this.staticMethod()} from another static method`;
}
}
StaticMethodCall.staticMethod();
// 'Static method and static property has been called'
StaticMethodCall.anotherStaticMethod();
// 'Static method and static property has been called from another static method'
### Calling static members from a class constructor and other methods
Static members are not directly accessible using the `this` keyword from non-
static methods. You need to call them using the class name:
`CLASSNAME.STATIC_METHOD_NAME()` / `CLASSNAME.STATIC_PROPERTY_NAME` or by
calling the method as a property of the `constructor`:
`this.constructor.STATIC_METHOD_NAME()` /
`this.constructor.STATIC_PROPERTY_NAME`
class StaticMethodCall {
constructor() {
console.log(StaticMethodCall.staticProperty); // 'static property'
console.log(this.constructor.staticProperty); // 'static property'
console.log(StaticMethodCall.staticMethod()); // 'static method has been called.'
console.log(this.constructor.staticMethod()); // 'static method has been called.'
}
static staticProperty = "static property";
static staticMethod() {
return "static method has been called.";
}
}
## Specifications
## Browser compatibility
| Desktop | Mobile | Server
---|---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android | Deno | Node.js
`static` | 4942–49Strict mode is required. | 13 | 45 | 3629–36Strict mode is required. | 9 | 4942–49Strict mode is required. | 45 | 3629–36Strict mode is required. | 9 | 5.04.0–5.0Strict mode is required. | 4942–49Strict mode is required. | 1.0 | 6.0.0
## See also
* Using classes guide
* Classes
* Static initialization blocks
* `class`
# Static initialization blocks
Baseline 2023
Newly available
Since March 2023, this feature works across the latest devices and browser
versions. This feature might not work in older devices or browsers.
* Learn more
* See full compatibility
* Report feedback
**Static initialization blocks** are declared within a `class`. It contains
statements to be evaluated during class initialization. This permits more
flexible initialization logic than `static` properties, such as using
`try...catch` or setting multiple fields from a single value. Initialization
is performed in the context of the current class declaration, with access to
private state, which allows the class to share information of its private
properties with other classes or functions declared in the same scope
(analogous to "friend" classes in C++).
## Try it
class ClassWithStaticInitializationBlock {
static staticProperty1 = "Property 1";
static staticProperty2;
static {
this.staticProperty2 = "Property 2";
}
}
console.log(ClassWithStaticInitializationBlock.staticProperty1);
// Expected output: "Property 1"
console.log(ClassWithStaticInitializationBlock.staticProperty2);
// Expected output: "Property 2"
## Syntax
class ClassWithSIB {
static {
// …
}
}
## Description
Without static initialization blocks, complex static initialization might be
achieved by calling a static method after the class declaration:
class MyClass {
static init() {
// Access to private static fields is allowed here
}
}
MyClass.init();
However, this approach exposes an implementation detail (the `init()` method)
to the user of the class. On the other hand, any initialization logic declared
outside the class does not have access to private static fields. Static
initialization blocks allow arbitrary initialization logic to be declared
within the class and executed during class evaluation.
A `class` can have any number of `static {}` initialization blocks in its
class body. These are evaluated, along with any interleaved static field
initializers, in the order they are declared. Any static initialization of a
super class is performed first, before that of its sub classes.
The scope of the variables declared inside the static block is local to the
block. This includes `var`, `function`, `const`, and `let` declarations. `var`
declarations will not be hoisted out of the static block.
var y = "Outer y";
class A {
static field = "Inner y";
static {
// var y only hoisted inside block
console.log(y); // undefined <-- not 'Outer y'
var y = this.field;
}
}
// var y defined in static block is not hoisted
// outside the block
console.log(y); // 'Outer y'
The `this` inside a static block refers to the constructor object of the
class. `super.property` can be used to access static properties of the super
class. Note however that it is a syntax error to call `super()` in a class
static initialization block, or to use the `arguments` object.
The statements are evaluated synchronously. You cannot use `await` or `yield`
in this block. (Think of the initialization statements as being implicitly
wrapped in a function.)
The scope of the static block is nested _within_ the lexical scope of the
class body, and can access private names declared within the class without
causing a syntax error.
Static field initializers and static initialization blocks are evaluated one-
by-one. The initialization block can refer to field values above it, but not
below it. All static methods are added beforehand and can be accessed,
although calling them may not behave as expected if they refer to fields below
the current block.
**Note:** This is more important with private static fields, because accessing
a non-initialized private field throws a `TypeError`, even if the private
field is declared below. (If the private field is not declared, it would be an
early `SyntaxError`.)
A static initialization block may not have decorators (the class itself may).
## Examples
### Multiple blocks
The code below demonstrates a class with static initialization blocks and
interleaved static field initializers. The output shows that the blocks and
fields are evaluated in execution order.
class MyClass {
static field1 = console.log("static field1");
static {
console.log("static block1");
}
static field2 = console.log("static field2");
static {
console.log("static block2");
}
}
// 'static field1'
// 'static block1'
// 'static field2'
// 'static block2'
Note that any static initialization of a super class is performed first,
before that of its sub classes.
### Using this and super
The `this` inside a static block refers to the constructor object of the
class. This code shows how to access a public static field.
class A {
static field = "static field";
static {
console.log(this.field);
}
}
// 'static field'
The `super.property` syntax can be used inside a `static` block to reference
static properties of a super class.
class A {
static field = "static field";
}
class B extends A {
static {
console.log(super.field);
}
}
// 'static field'
### Access to private properties
This example below shows how access can be granted to a private instance field
of a class from an object outside the class (example from the v8.dev blog):
let getDPrivateField;
class D {
#privateField;
constructor(v) {
this.#privateField = v;
}
static {
getDPrivateField = (d) => d.#privateField;
}
}
console.log(getDPrivateField(new D("private"))); // 'private'
## Specifications
## Browser compatibility
| Desktop | Mobile | Server
---|---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android | Deno | Node.js
`Static_initialization_blocks` | 94 | 94 | 93 | 80 | 16.4 | 94 | 93 | 66 | 16.4 | 17.0 | 94 | 1.14 | 16.11.0
## See also
* Using classes guide
* Classes
* `static`
* `class`
* Class static initialization blocks on v8.dev (2021)
* ES2022 feature: class static initialization blocks by Dr. Axel Rauschmayer (2021)
# JavaScript error reference
Below, you'll find a list of errors which are thrown by JavaScript. These
errors can be a helpful debugging aid, but the reported problem isn't always
immediately clear. The pages below will provide additional details about these
errors. Each error is an object based upon the `Error` object, and has a
`name` and a `message`.
Errors displayed in the Web console may include a link to the corresponding
page below to help you quickly comprehend the problem in your code.
For a beginner's introductory tutorial on fixing JavaScript errors, see What
went wrong? Troubleshooting JavaScript.
## List of errors
In this list, each page is listed by name (the type of error) and message (a
more detailed human-readable error message). Together, these two properties
provide a starting point toward understanding and resolving the error. For
more information, follow the links below!
* AggregateError: No Promise in Promise.any was resolved
* Error: Permission denied to access property "x"
* InternalError: too much recursion
* RangeError: BigInt division by zero
* RangeError: BigInt negative exponent
* RangeError: argument is not a valid code point
* RangeError: form must be one of 'NFC', 'NFD', 'NFKC', or 'NFKD'
* RangeError: invalid array length
* RangeError: invalid date
* RangeError: precision is out of range
* RangeError: radix must be an integer
* RangeError: repeat count must be less than infinity
* RangeError: repeat count must be non-negative
* RangeError: x can't be converted to BigInt because it isn't an integer
* ReferenceError: "x" is not defined
* ReferenceError: assignment to undeclared variable "x"
* ReferenceError: can't access lexical declaration 'X' before initialization
* ReferenceError: must call super constructor before using 'this' in derived class constructor
* ReferenceError: super() called twice in derived class constructor
* SyntaxError: "0"-prefixed octal literals are deprecated
* SyntaxError: "use strict" not allowed in function with non-simple parameters
* SyntaxError: "x" is a reserved identifier
* SyntaxError: 'arguments'/'eval' can't be defined or assigned to in strict mode code
* SyntaxError: JSON.parse: bad parsing
* SyntaxError: Unexpected '#' used outside of class body
* SyntaxError: Unexpected token
* SyntaxError: Using //@ to indicate sourceURL pragmas is deprecated. Use //# instead
* SyntaxError: \ at end of pattern
* SyntaxError: a declaration in the head of a for-of loop can't have an initializer
* SyntaxError: applying the 'delete' operator to an unqualified name is deprecated
* SyntaxError: arguments is not valid in fields
* SyntaxError: await is only valid in async functions, async generators and modules
* SyntaxError: await/yield expression can't be used in parameter
* SyntaxError: cannot use `??` unparenthesized within `||` and `&&` expressions
* SyntaxError: character class escape cannot be used in class range in regular expression
* SyntaxError: continue must be inside loop
* SyntaxError: duplicate capture group name in regular expression
* SyntaxError: duplicate formal argument x
* SyntaxError: for-in loop head declarations may not have initializers
* SyntaxError: function statement requires a name
* SyntaxError: functions cannot be labelled
* SyntaxError: getter and setter for private name #x should either be both static or non-static
* SyntaxError: getter functions must have no arguments
* SyntaxError: identifier starts immediately after numeric literal
* SyntaxError: illegal character
* SyntaxError: import declarations may only appear at top level of a module
* SyntaxError: incomplete quantifier in regular expression
* SyntaxError: invalid BigInt syntax
* SyntaxError: invalid assignment left-hand side
* SyntaxError: invalid capture group name in regular expression
* SyntaxError: invalid character in class in regular expression
* SyntaxError: invalid class set operation in regular expression
* SyntaxError: invalid decimal escape in regular expression
* SyntaxError: invalid identity escape in regular expression
* SyntaxError: invalid named capture reference in regular expression
* SyntaxError: invalid property name in regular expression
* SyntaxError: invalid range in character class
* SyntaxError: invalid regexp group
* SyntaxError: invalid regular expression flag "x"
* SyntaxError: invalid unicode escape in regular expression
* SyntaxError: label not found
* SyntaxError: missing ) after argument list
* SyntaxError: missing ) after condition
* SyntaxError: missing : after property id
* SyntaxError: missing = in const declaration
* SyntaxError: missing ] after element list
* SyntaxError: missing formal parameter
* SyntaxError: missing name after . operator
* SyntaxError: missing variable name
* SyntaxError: missing } after function body
* SyntaxError: missing } after property list
* SyntaxError: negated character class with strings in regular expression
* SyntaxError: new keyword cannot be used with an optional chain
* SyntaxError: nothing to repeat
* SyntaxError: numbers out of order in {} quantifier.
* SyntaxError: octal escape sequences can't be used in untagged template literals or in strict mode code
* SyntaxError: parameter after rest parameter
* SyntaxError: private fields can't be deleted
* SyntaxError: property name __proto__ appears more than once in object literal
* SyntaxError: raw bracket is not allowed in regular expression with unicode flag
* SyntaxError: redeclaration of formal parameter "x"
* SyntaxError: reference to undeclared private field or method #x
* SyntaxError: rest parameter may not have a default
* SyntaxError: return not in function
* SyntaxError: setter functions must have one argument
* SyntaxError: string literal contains an unescaped line break
* SyntaxError: super() is only valid in derived class constructors
* SyntaxError: tagged template cannot be used with optional chain
* SyntaxError: unlabeled break must be inside loop or switch
* SyntaxError: unparenthesized unary expression can't appear on the left-hand side of '**'
* SyntaxError: use of super property/member accesses only valid within methods or eval code within methods
* TypeError: "x" is (not) "y"
* TypeError: "x" is not a constructor
* TypeError: "x" is not a function
* TypeError: "x" is not a non-null object
* TypeError: "x" is read-only
* TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed
* TypeError: 'x' is not iterable
* TypeError: BigInt value can't be serialized in JSON
* TypeError: Initializing an object twice is an error with private fields/methods
* TypeError: Iterator/AsyncIterator constructor can't be used directly
* TypeError: More arguments needed
* TypeError: Reduce of empty array with no initial value
* TypeError: WeakSet key/WeakMap value 'x' must be an object or an unregistered symbol
* TypeError: X.prototype.y called on incompatible type
* TypeError: already executing generator
* TypeError: calling a builtin X constructor without new is forbidden
* TypeError: can't access/set private field or method: object is not the right class
* TypeError: can't assign to property "x" on "y": not an object
* TypeError: can't convert BigInt to number
* TypeError: can't convert x to BigInt
* TypeError: can't define property "x": "obj" is not extensible
* TypeError: can't delete non-configurable array element
* TypeError: can't redefine non-configurable property "x"
* TypeError: can't set prototype of this object
* TypeError: can't set prototype: it would cause a prototype chain cycle
* TypeError: cannot use 'in' operator to search for 'x' in 'y'
* TypeError: class constructors must be invoked with 'new'
* TypeError: cyclic object value
* TypeError: derived class constructor returned invalid value x
* TypeError: getting private setter-only property
* TypeError: invalid 'instanceof' operand 'x'
* TypeError: invalid Array.prototype.sort argument
* TypeError: invalid assignment to const "x"
* TypeError: matchAll/replaceAll must be called with a global RegExp
* TypeError: null/undefined has no properties
* TypeError: property "x" is non-configurable and can't be deleted
* TypeError: setting getter-only property "x"
* URIError: malformed URI sequence
* Warning: -file- is being assigned a //# sourceMappingURL, but already has one
* Warning: unreachable code after return statement
# TypeError: already executing generator
The JavaScript exception "TypeError: already executing generator" occurs when
a generator is continued using one of its methods (such as `next()`) while
executing the generator function's body itself.
## Message
TypeError: Generator is already running (V8-based)
TypeError: already executing generator (Firefox)
TypeError: Generator is executing (Safari)
## Error type
`TypeError`
## What went wrong?
The generator's methods, `next()`, `return()`, and `throw()`, are meant to
continue the execution of a generator function when it's paused after a
`yield` expression or before the first statement. If a call to one of these
methods is made while executing the generator function, the error is thrown.
If you want to return or throw within the generator function, use the `return`
statement or the `throw` statement, respectively.
## Examples
let it;
function* getNumbers(times) {
if (times <= 0) {
it.throw(new Error("times must be greater than 0"));
}
for (let i = 0; i < times; i++) {
yield i;
}
}
it = getNumbers(3);
it.next();
let it;
function* getNumbers(times) {
if (times <= 0) {
throw new Error("times must be greater than 0");
}
for (let i = 0; i < times; i++) {
yield i;
}
}
it = getNumbers(3);
it.next(); // { value: 0, done: false }
## See also
* Iterators and generators
* Iteration protocols
* `function*`
* `Generator`
# Warning: -file- is being assigned a //# sourceMappingURL, but already has
one
The JavaScript warning "-file- is being assigned a //# sourceMappingURL, but
already has one." occurs when a source map has been specified more than once
for a given JavaScript source.
## Message
Warning: -file- is being assigned a //# sourceMappingURL, but already has one.
## Error type
A warning. JavaScript execution won't be halted.
## What went wrong?
A source map has been specified more than once for a given JavaScript source.
JavaScript sources are often combined and minified to make delivering them
from the server more efficient. With source maps, the debugger can map the
code being executed to the original source files. There are two ways to assign
a source map, either by using a comment or by setting a header to the
JavaScript file.
## Examples
### Setting source maps
Setting a source map by using a comment in the file:
//# sourceMappingURL=http://example.com/path/to/your/sourcemap.map
Or, alternatively, you can set a header to your JavaScript file:
X-SourceMap: /path/to/file.js.map
## See also
* Use a source map in the Firefox source docs
* Introduction to JavaScript source maps on developer.chrome.com (2012)
# SyntaxError: arguments is not valid in fields
The JavaScript exception "SyntaxError: arguments is not valid in fields"
occurs when the `arguments` identifier is read in a class field initializer or
in a static initialization block, outside of a non-arrow function.
## Message
SyntaxError: 'arguments' is not allowed in class field initializer or static initialization block (V8-based)
SyntaxError: arguments is not valid in fields (Firefox)
SyntaxError: Unexpected identifier 'arguments'. Cannot reference 'arguments' in class field initializer. (Safari)
## Error type
`SyntaxError`
## What went wrong?
A class field initializer expression or a class static initialization block
does not have `arguments` in its scope. Trying to access it is a syntax error.
* This is true even if `arguments` is bound in a parent scope (such as when the class is nested in a non-arrow function).
* A non-arrow function declared within this scope will still bind its own `arguments` and read it normally.
## Examples
function makeOne() {
class C {
args = { ...arguments }; // SyntaxError: arguments is not valid in fields
}
return new C();
}
let CArgs;
class C {
static {
CArgs = arguments; // SyntaxError: arguments is not valid in fields
}
}
class C {
args = {};
constructor() {
this.args = arguments; // You can use arguments in constructors
}
myMethod() {
this.args = arguments; // You can also use it in methods
}
}
function makeOne() {
const _arguments = arguments;
class C {
args = { ..._arguments }; // Only the identifier is forbidden
}
return new C();
}
## See also
* Classes
* Public class fields
* Static initialization blocks
# TypeError: invalid Array.prototype.sort argument
The JavaScript exception "invalid Array.prototype.sort argument" occurs when
the argument of `Array.prototype.sort()` (and its related methods:
`Array.prototype.toSorted()`, `TypedArray.prototype.sort()`,
`TypedArray.prototype.toSorted()`) isn't either `undefined` or a function
which compares its operands.
## Message
TypeError: The comparison function must be either a function or undefined (V8-based)
TypeError: invalid Array.prototype.sort argument (Firefox)
TypeError: non-function passed to Array.prototype.toSorted (Firefox)
TypeError: invalid %TypedArray%.prototype.sort argument (Firefox)
TypeError: Array.prototype.sort requires the comparator argument to be a function or undefined (Safari)
TypeError: Array.prototype.toSorted requires the comparator argument to be a function or undefined (Safari)
TypeError: TypedArray.prototype.sort requires the comparator argument to be a function or undefined (Safari)
TypeError: TypedArray.prototype.toSorted requires the comparator argument to be a function or undefined (Safari)
## Error type
`TypeError`
## What went wrong?
The argument of `Array.prototype.sort()` (and its related methods:
`Array.prototype.toSorted()`, `TypedArray.prototype.sort()`,
`TypedArray.prototype.toSorted()`) is expected to be either `undefined` or a
function which compares its operands.
## Examples
### Invalid cases
[1, 3, 2].sort(5); // TypeError
students.toSorted("name"); // TypeError
### Valid cases
[1, 3, 2].sort(); // [1, 2, 3]
[1, 3, 2].sort((a, b) => a - b); // [1, 2, 3]
students.toSorted((a, b) => a.name.localeCompare(b.name));
## See also
* `Array.prototype.sort()`
* `Array.prototype.toSorted()`
* `TypedArray.prototype.sort()`
* `TypedArray.prototype.toSorted()`
# SyntaxError: await/yield expression can't be used in parameter
The JavaScript exception "await expression can't be used in parameter" or
"yield expression can't be used in parameter" occurs when the default
parameter expression contains the `await` or `yield` keyword and has the
effect of pausing default parameter evaluation.
## Message
SyntaxError: Illegal await-expression in formal parameters of async function (V8-based)
SyntaxError: await expression can't be used in parameter (Firefox)
SyntaxError: Cannot use 'await' within a parameter default expression. (Safari)
SyntaxError: Yield expression not allowed in formal parameter (V8-based)
SyntaxError: yield expression can't be used in parameter (Firefox)
SyntaxError: Unexpected keyword 'yield'. Cannot use yield expression within parameters. (Safari)
## Error type
`SyntaxError`
## What went wrong?
The default expression must be able to evaluate _synchronously_. If it
contains an `await` or `yield` expression, it will pause the evaluation of the
default expression, which is not allowed.
**Note:** This error is only generated when `await` or `yield` are valid
operators in this function context. Otherwise, `await` or `yield` would be
parsed as an identifier, and either not cause an error, or cause an error like
"reserved identifier", or "unexpected token" if there's an expression
following it.
## Examples
### Invalid cases
function *gen(a = yield 1) {}
async function f(a = await Promise.resolve(1)) {}
### Valid cases
You can use the nullish coalescing assignment to provide a default value
instead. If you want to treat `null` and `undefined` differently, you would
need to use a condition.
function* gen(a) {
a ??= yield 1;
}
async function f(a) {
a ??= await Promise.resolve(1);
}
You are also allowed to use `await` or `yield` if the expression is contained
in a function expression of the initializer and would not pause the evaluation
of the default expression.
async function f(a = (async () => await Promise.resolve(1))()) {}
## See also
* Default parameters
* `await`
* `yield`
# SyntaxError: await is only valid in async functions, async generators and
modules
The JavaScript exception "await is only valid in async functions, async
generators and modules" occurs when an `await` expression is used outside of
async functions or modules or other async contexts.
## Message
SyntaxError: await is only valid in async functions and the top level bodies of modules (V8-based)
SyntaxError: await is only valid in async functions, async generators and modules (Firefox)
SyntaxError: Unexpected identifier (Safari)
## Error type
`SyntaxError`.
## What went wrong?
JavaScript execution is never blocking: an `await` can never block the
execution of the program. Instead, it pauses the execution of the surrounding
async task, while allowing other tasks to continue running. Therefore, `await`
cannot be used in sync tasks, such as functions, generator functions, or top
level of scripts. It is not always apparent whether the current file is a
script or a module — see the Modules guide for more information.
## Examples
### Top-level await
You cannot use `await` at the top level of a script:
Instead, make the script a module:
### Async callbacks
You cannot use `await` in a sync callback:
urls.forEach((url) => {
await fetch(url);
// SyntaxError: await is only valid in async functions, async generators and modules
});
Instead, make the callback async. See more explanation in the Using promises
guide.
Promise.all(
urls.map(async (url) => {
await fetch(url);
}),
);
## See also
* `await`
# SyntaxError: unlabeled break must be inside loop or switch
The JavaScript exception "unlabeled break must be inside loop or switch"
occurs when a `break` statement is not inside a loop or a `switch` statement.
## Message
SyntaxError: Illegal break statement (V8-based)
SyntaxError: unlabeled break must be inside loop or switch (Firefox)
SyntaxError: 'break' is only valid inside a switch or loop statement. (Safari)
## Error type
`SyntaxError`.
## What went wrong?
`break` statements can be used to exit a loop or a `switch` statement, and
using them elsewhere is a syntax error. Alternatively, you can provide a label
to the `break` statement to break out of any statement with that label —
however, if the label does not reference a containing statement, another error
SyntaxError: label not found will be thrown.
## Examples
### Unsyntactic break
`break` cannot be used outside `switch` or loops.
let score = 0;
function increment() {
if (score === 100)
break; // SyntaxError: unlabeled break must be inside loop or switch
}
score++;
}
Maybe instead of `break`, you intend to use `return` to early-terminate a
function.
let score = 0;
function increment() {
if (score === 100) {
return;
}
score++;
}
### Using break in callbacks
`break` cannot be used in callbacks, even if the callback is called from a
loop.
let containingIndex = 0;
const matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
while (containingIndex < matrix.length) {
matrix[containingIndex].forEach((value) => {
if (value === 5) {
break; // SyntaxError: unlabeled break must be inside loop or switch
}
});
containingIndex++;
}
Instead, refactor the code so the `break` is used outside the callback.
let containingIndex = 0;
const matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
outer: while (containingIndex < matrix.length) {
for (const value of matrix[containingIndex]) {
if (value === 5) {
break outer;
}
}
containingIndex++;
}
let containingIndex = 0;
const matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
while (containingIndex < matrix.length) {
if (matrix[containingIndex].includes(5)) {
break;
}
containingIndex++;
}
There's no way to early-terminate a `forEach()` loop. You can use `some()`
instead, or convert it to a `for...of` loop.
array.forEach((value) => {
if (value === 5) {
break; // SyntaxError: unlabeled break must be inside loop or switch
}
// do something with value
});
array.some((value) => {
if (value === 5) {
return true;
}
// do something with value
return false;
});
for (const value of array) {
if (value === 5) {
break;
}
// do something with value
}
## See also
* `break`
# SyntaxError: continue must be inside loop
The JavaScript exception "continue must be inside loop" occurs when a
`continue` statement is not inside a loop statement.
## Message
SyntaxError: Illegal continue statement: no surrounding iteration statement (V8-based)
SyntaxError: Illegal continue statement: 'label' does not denote an iteration statement (V8-based)
SyntaxError: continue must be inside loop (Firefox)
SyntaxError: 'continue' is only valid inside a loop statement. (Safari)
SyntaxError: Cannot continue to the label 'label' as it is not targeting a loop. (Safari)
## Error type
`SyntaxError`.
## What went wrong?
`continue` statements can be used to continue a loop, and using them elsewhere
is a syntax error. Alternatively, you can provide a label to the `continue`
statement to continue any loop with that label — however, if the label does
not reference a containing statement, another error SyntaxError: label not
found will be thrown, and if the label references a statement that is not a
loop, a syntax error is still thrown.
## Examples
### Using continue in callbacks
If you want to proceed with the next iteration in a `forEach()` loop, use
`return` instead, or convert it to a `for...of` loop.
array.forEach((value) => {
if (value === 5) {
continue; // SyntaxError: continue must be inside loop
}
// do something with value
});
array.forEach((value) => {
if (value === 5) {
return;
}
// do something with value
});
for (const value of array) {
if (value === 5) {
continue;
}
// do something with value
}
## See also
* `continue`
# SyntaxError: new keyword cannot be used with an optional chain
The JavaScript exception "new keyword cannot be used with an optional chain"
occurs when the constructor of a `new` expression is an optional chain, or if
there's an optional chain between the constructor and the parenthesized list
of arguments.
## Message
SyntaxError: Invalid optional chain from new expression (V8-based)
SyntaxError: new keyword cannot be used with an optional chain (Firefox)
SyntaxError: Cannot call constructor in an optional chain. (Safari)
## Error type
`SyntaxError`
## What went wrong?
There are two ways to get this error. The first one is if the constructor
expression is an optional chain expression, like this:
new Intl?.DateTimeFormat();
Number?.[parseMethod]`Hello, world!`;
The second one is if `?.` occurs between the constructor and the arguments
list, like this:
new Intl.DateTimeFormat?.();
Optional `new` is specifically forbidden because its syntax is complicated
(`new` with and without arguments), and the result is unclear (it would be the
only case where `new` does not evaluate to an object value). You need to
translate the optional chaining to its underlying condition (see optional
chaining for more information).
const result =
Intl.DateTimeFormat === null || Intl.DateTimeFormat === undefined
? undefined
: new Intl.DateTimeFormat();
Remember that optional chaining only short-circuits within a parenthesized
unit. If you parenthesize your constructor expression, the optional chaining
will not cause an error, because now the constructor does not short-circuit
and the result is clear (the constructor will produce `undefined` and then
cause the `new` expression to throw).
new (Intl?.DateTimeFormat)(); // Throws if Intl?.DateTimeFormat is undefined
However this is a bit nonsensical anyway because optional chaining prevents
errors inside the property access chain, but is then guaranteed to generate an
error when calling `new`. You would probably still want to use a conditional
check.
Note that optional chaining is only forbidden as the constructor expression.
You can use optional chaining inside the argument list, or use optional
chaining on the `new` expression as a whole.
new Intl.DateTimeFormat(navigator?.languages);
new Intl.DateTimeFormat().resolvedOptions?.();
Note that there's no needs to use `?.` on the `new` expression itself: `new
a()?.b`, because `new` is guaranteed to produce a non-nullish object value.
## See also
* `new`
* Optional chaining (`?.`)
* Original discussion on whether "optional new" should be allowed
# SyntaxError: tagged template cannot be used with optional chain
The JavaScript exception "tagged template cannot be used with optional chain"
occurs when the tag expression of a tagged template literal is an optional
chain, or if there's an optional chain between the tag and the template.
## Message
SyntaxError: Invalid tagged template on optional chain (V8-based)
SyntaxError: tagged template cannot be used with optional chain (Firefox)
SyntaxError: Cannot use tagged templates in an optional chain. (Safari)
## Error type
`SyntaxError`
## What went wrong?
There are two ways to get this error. The first one is if the tag expression
is an optional chain expression, like this:
String?.raw`Hello, world!`;
console.log?.()`Hello, world!`;
Number?.[parseMethod]`Hello, world!`;
The second one is if `?.` occurs between the tag and the template, like this:
String.raw?.`Hello, world!`;
Optional chaining in the tag is specifically forbidden because there's no
great use case for it, and what the result is expected to be is unclear
(should it be `undefined` or the template's value as if it's untagged?). You
need to translate the optional chaining to its underlying condition (see
optional chaining for more information).
const result =
String.raw === null || String.raw === undefined
? undefined
: String.raw`Hello, world!`;
Remember that optional chaining only short-circuits within a parenthesized
unit. If you parenthesize your tag expression, the optional chaining will not
cause an error, because now the tag does not short-circuit and the result is
clear (the tag will produce `undefined` and then cause the tagged template to
throw).
(console?.log)`Hello, world!`; // Throws if console?.log is undefined
However this is a bit nonsensical anyway because optional chaining prevents
errors inside the property access chain, but is then guaranteed to generate an
error when calling the template tag. You would probably still want to use a
conditional check.
Note that optional chaining is only forbidden as the tag expression. You can
use optional chaining inside the embedded expressions, or use optional
chaining on the tagged template expression as a whole.
console.log`Hello, ${true.constructor?.name}!`; // ['Hello, ', '!', raw: Array(2)] 'Boolean'
console.log`Hello`?.toString(); // undefined
## See also
* Template literals
* Optional chaining (`?.`)
* Original discussion on whether optional chaining should be allowed in tagged template literals
# RangeError: radix must be an integer
The JavaScript exception "radix must be an integer at least 2 and no greater
than 36" occurs when the optional `radix` parameter of the
`Number.prototype.toString()` or the `BigInt.prototype.toString()` method was
specified and is not between 2 and 36.
## Message
RangeError: toString() radix argument must be between 2 and 36 (V8-based & Safari)
RangeError: radix must be an integer at least 2 and no greater than 36 (Firefox)
## Error type
`RangeError`
## What went wrong?
The optional `radix` parameter of the `Number.prototype.toString()` or the
`BigInt.prototype.toString()` method was specified. Its value must be an
integer (a number) between 2 and 36, specifying the base of the number system
to be used for representing numeric values. For example, the decimal (base 10)
number 169 is represented in hexadecimal (base 16) as A9.
Why is this parameter's value limited to 36? A radix that is larger than 10
uses alphabetical characters as digits; therefore, the radix can't be larger
than 36, since the Latin alphabet (used by English and many other languages)
only has 26 characters.
The most common radixes:
* 2 for binary numbers,
* 8 for octal numbers,
* 10 for decimal numbers,
* 16 for hexadecimal numbers.
## Examples
### Invalid cases
(42).toString(0);
(42).toString(1);
(42).toString(37);
(42).toString(150);
// You cannot use a string like this for formatting:
(12071989).toString("MM-dd-yyyy");
### Valid cases
(42).toString(2); // "101010" (binary)
(13).toString(8); // "15" (octal)
(0x42).toString(10); // "66" (decimal)
(100000).toString(16); // "186a0" (hexadecimal)
## See also
* `Number.prototype.toString()`
* `BigInt.prototype.toString()`
# SyntaxError: invalid regular expression flag "x"
The JavaScript exception "invalid regular expression flag" occurs when the
flags in a regular expression contain any flag that is not one of: `d`, `g`,
`i`, `m`, `s`, `u`, `v`, or `y`. It may also be raised if the expression
contains more than one instance of a valid flag, or when the `u` and `v` flags
are used together.
## Message
SyntaxError: Invalid flags supplied to RegExp constructor 'x' (V8-based)
SyntaxError: Invalid regular expression flags (V8-based)
SyntaxError: invalid regular expression flag x (Firefox)
SyntaxError: Invalid flags supplied to RegExp constructor. (Safari)
SyntaxError: Invalid regular expression: invalid flags (Safari)
## Error type
`SyntaxError`
## What went wrong?
The regular expression contains invalid flags, or valid flags have been used
more than once in the expression.
The valid (allowed) flags are `d`, `g`, `i`, `m`, `s`, `u`, `v`, and `y`. They
are introduced in more detail in Regular expressions > Advanced searching with
flags.
The `u` and `v` flags are mutually exclusive, so they cannot be used together.
You can read the references to understand what their behavior differences are.
## Examples
In a regular expression literal, which consists of a pattern enclosed between
slashes, the flags are defined after the second slash. Regular expression
flags can be used separately or together in any order. This syntax shows how
to declare the flags using the regular expression literal:
const re = /pattern/flags;
They can also be defined in the constructor function of the `RegExp` object
(second parameter):
const re = new RegExp("pattern", "flags");
Here is an example showing use of only correct flags.
/foo/g;
/foo/gims;
/foo/uy;
Below is an example showing the use of some invalid flags `b`, `a` and `r`:
/foo/bar;
// SyntaxError: invalid regular expression flag "b"
The code below is incorrect, because `W`, `e` and `b` are not valid flags.
const obj = {
url: /docs/Web,
};
// SyntaxError: invalid regular expression flag "W"
An expression containing two slashes is interpreted as a regular expression
literal. Most likely the intent was to create a string literal, using single
or double quotes as shown below:
const obj = {
url: "/docs/Web",
};
## See also
* Regular expressions guide
# SyntaxError: return not in function
The JavaScript exception "return not in function" occurs when a `return`
statement is called outside of a function.
## Message
SyntaxError: Illegal return statement (V8-based)
SyntaxError: return not in function (Firefox)
SyntaxError: Return statements are only valid inside functions. (Safari)
## Error type
`SyntaxError`.
## What went wrong?
A `return` statement is called outside of a function. Maybe there are missing
curly braces somewhere? The `return` statement must be in a function, because
it ends function execution and specifies a value to be returned to the
function caller.
## Examples
### Missing curly braces
function cheer(score) {
if (score === 147)
return "Maximum!";
}
if (score > 100) {
return "Century!";
}
}
// SyntaxError: return not in function
The curly braces look correct at a first glance, but this code snippet is
missing a `{` after the first `if` statement. Correct would be:
function cheer(score) {
if (score === 147) {
return "Maximum!";
}
if (score > 100) {
return "Century!";
}
}
## See also
* `return`
# SyntaxError: 'arguments'/'eval' can't be defined or assigned to in strict
mode code
The JavaScript strict mode-only exception "'arguments' can't be defined or
assigned to in strict mode code" or "'eval' can't be defined or assigned to in
strict mode code" occurs when attempting to create a binding called
`arguments` or `eval`, or assign to such a name.
## Message
SyntaxError: Unexpected eval or arguments in strict mode (V8-based)
SyntaxError: 'arguments' can't be defined or assigned to in strict mode code (Firefox)
SyntaxError: Cannot modify 'arguments' in strict mode. (Safari)
SyntaxError: Cannot destructure to a parameter name 'arguments' in strict mode. (Safari)
SyntaxError: Cannot declare a variable named arguments in strict mode. (Safari)
SyntaxError: Cannot declare a catch variable named 'arguments' in strict mode. (Safari)
SyntaxError: 'arguments' is not a valid function name in strict mode. (Safari)
## Error type
`SyntaxError`
## What went wrong?
In strict mode, the names `arguments` and `eval` behave as if they are
reserved words: you cannot make they refer to anything other than the
`arguments` object in functions or the global `eval` function.
## Examples
### Invalid cases
"use strict";
const arguments = [1, 2, 3];
console.log(Math.max(...arguments));
function foo(...arguments) {
console.log(arguments);
}
### Valid cases
"use strict";
const args = [1, 2, 3];
console.log(Math.max(...args));
function foo(...args) {
console.log(args);
}
## See also
* Strict mode
* `arguments`
* `eval()`
# SyntaxError: super() is only valid in derived class constructors
The JavaScript exception "super() is only valid in derived class constructors"
occurs when the `super()` call is used somewhere that's not the body of a
constructor in a class with `extends` keyword.
## Message
SyntaxError: 'super' keyword unexpected here (V8-based)
SyntaxError: super() is only valid in derived class constructors (Firefox)
SyntaxError: super is not valid in this context. (Safari)
## Error type
`SyntaxError`
## What went wrong?
The `super()` call is used to invoke the base constructor of a derived class,
so the base class can initialize the `this` object. Using it anywhere else
doesn't make sense.
`super()` can also be defined in an arrow function that's nested within the
constructor. However, it cannot be defined in any other kind of function.
## Examples
### Invalid cases
You cannot call `super()` if the class has no `extends`, because there's no
base class to call:
class Base {
constructor() {
super();
}
}
You cannot call `super()` in a class method, even if that method is called
from the constructor:
class Base {}
class Derived extends Base {
constructor() {
this.init();
}
init() {
super();
}
}
You cannot call `super()` in a function, even if the function is used as a
constructor:
function Base(x) {
this.x = x;
}
function Derived() {
super(1);
}
Object.setPrototypeOf(Derived.prototype, Base.prototype);
Object.setPrototypeOf(Derived, Base);
### Valid cases
You can call `super()` before calling any other method in the constructor:
class Base {}
class Derived extends Base {
constructor() {
super();
this.init();
}
init() {
// …
}
}
You can call `super()` in an arrow function that's nested within the
constructor:
class Base {}
class Derived extends Base {
constructor() {
const init = () => {
super();
};
init();
}
}
## See also
* Classes
* `super`
# SyntaxError: use of super property/member accesses only valid within methods
or eval code within methods
The JavaScript exception "use of super property/member accesses only valid
within methods or eval code within methods" occurs when the `super.x` or
`super[x]` syntax is used outside of a method.
## Message
SyntaxError: 'super' keyword unexpected here (V8-based)
SyntaxError: use of super property accesses only valid within methods or eval code within methods (Firefox)
SyntaxError: super is not valid in this context. (Safari)
## Error type
`SyntaxError`
## What went wrong?
The `super.x` syntax is used to access properties on the prototype of the
current object. It can be used in methods of both object literals and classes,
field initializers, and static initialization blocks, but not in other
contexts.
## Examples
### Invalid cases
You can't use `super.x` outside of a method in an object:
const obj = {
__proto__: { x: 1 },
x: super.x, // SyntaxError: use of super property accesses only valid within methods or eval code within methods
};
You can't use `super.x` in a function, even if that function has the effect of
being a method:
function getX() {
return super.x; // SyntaxError: use of super property accesses only valid within methods or eval code within methods
}
const obj = {
getX,
getX2: function () {
return super.x; // SyntaxError: use of super property accesses only valid within methods or eval code within methods
},
};
class Derived extends Base {
getX = () => super.x;
}
### Valid cases
You can use `super.x` in a method:
class Base {
x = 1;
}
class Derived extends Base {
getX() {
return super.x;
}
}
You can use `super.x` in a field initializer:
class Derived extends Base {
x = super.x;
}
You can use `super.x` in object methods too:
const obj = {
__proto__: { x: 1 },
getX() {
return super.x;
},
};
## See also
* Classes
* `super`
# RangeError: BigInt division by zero
The JavaScript exception "BigInt division by zero" occurs when a `BigInt` is
divided by `0n`.
## Message
RangeError: Division by zero (V8-based)
RangeError: BigInt division by zero (Firefox)
RangeError: 0 is an invalid divisor value. (Safari)
## Error type
`RangeError`.
## What went wrong?
The divisor of a division or remainder operator is `0n`. In `Number`
arithmetic, this produces `Infinity`, but there's no "infinity value" in
BigInts, so an error is issued. Check if the divisor is `0n` before doing the
division.
## Examples
### Division by 0n
const a = 1n;
const b = 0n;
const quotient = a / b;
// RangeError: BigInt division by zero
Instead, check if the divisor is `0n` first, and either issue an error with a
better message, or fallback to a different value, like `Infinity` or
`undefined`.
const a = 1n;
const b = 0n;
const quotient = b === 0n ? undefined : a / b;
## See also
* `BigInt`
* Division (`/`)
* Remainder (`%`)
# RangeError: BigInt negative exponent
The JavaScript exception "BigInt negative exponent" occurs when a `BigInt` is
raised to the power of a negative BigInt value.
## Message
RangeError: Exponent must be positive (V8-based)
RangeError: BigInt negative exponent (Firefox)
RangeError: Negative exponent is not allowed (Safari)
## Error type
`RangeError`.
## What went wrong?
The exponent of an exponentiation operation must be positive. Since negative
exponents would take the reciprocal of the base, the result will be between -1
and 1 in almost all cases, which gets rounded to `0n`. To catch mistakes,
negative exponents are not allowed. Check if the exponent is non-negative
before doing exponentiation.
## Examples
### Using a negative BigInt as exponent
const a = 1n;
const b = -1n;
const c = a ** b;
// RangeError: BigInt negative exponent
Instead, check if the exponent is negative first, and either issue an error
with a better message, or fallback to a different value, like `0n` or
`undefined`.
const a = 1n;
const b = -1n;
const quotient = b >= 0n ? a ** b : 0n;
## See also
* `BigInt`
* Exponentiation (`**`)
# TypeError: BigInt value can't be serialized in JSON
The JavaScript exception "BigInt value can't be serialized in JSON" occurs
when a `BigInt` is encountered in `JSON.stringify` with no custom
serialization method provided.
## Message
TypeError: Do not know how to serialize a BigInt (V8-based)
TypeError: BigInt value can't be serialized in JSON (Firefox)
TypeError: JSON.stringify cannot serialize BigInt. (Safari)
## Error type
`TypeError`
## What went wrong?
You are trying to serialize a BigInt value using `JSON.stringify`, which does
not support BigInt values by default.Sometimes, JSON stringification happens
implicitly in libraries, as part of data serialization. For example, sending
data to the server, storing it in external storage, or transferring it between
threads would all require serialization, which is often done using JSON.
There are several ways to handle this:
* If you can alter the data source, avoid using BigInt values and cast it to a number first (which may lose precision for large numbers).
* If you can alter the stringification process, pass a replacer function to `JSON.stringify` that converts BigInt values to strings or numbers.
* You can also provide a `BigInt.prototype.toJSON` method globally that gets called whenever a BigInt value is stringified.
For more information on various tradeoffs, see BigInt reference.
## Examples
### Providing a custom serialization method
By default, BigInt values are not serializable in JSON:
const data = { a: 1n };
JSON.stringify(data);
// TypeError: BigInt value can't be serialized in JSON
Assuming you intend for the JSON to contain a number value, here are a few
approaches that work:
* Convert the BigInt to a number before stringifying:
const data = { a: 1n };
JSON.stringify({ ...data, a: Number(data.a) });
// '{"a":1}'
* Provide a replacer function that converts BigInt values to numbers or raw JSON objects:
const data = { a: 1n };
JSON.stringify(data, (key, value) =>
typeof value === "bigint" ? Number(value) : value,
);
// '{"a":1}'
const data = { a: 1n };
JSON.stringify(data, (key, value) =>
typeof value === "bigint" ? JSON.rawJSON(value.toString()) : value,
);
// '{"a":1}'
* Provide a `BigInt.prototype.toJSON` method that gets called whenever a BigInt value is stringified:
BigInt.prototype.toJSON = function () {
return Number(this);
};
const data = { a: 1n };
JSON.stringify(data);
// '{"a":1}'
BigInt.prototype.toJSON = function () {
return JSON.rawJSON(this.toString());
};
const data = { a: 1n };
JSON.stringify(data);
// '{"a":1}'
## See also
* `BigInt`
* `JSON.stringify()`
* `JSON.rawJSON()`
# TypeError: calling a builtin X constructor without new is forbidden
The JavaScript exception "calling a builtin X constructor without new is
forbidden" occurs when you try to call a builtin constructor without using the
`new` keyword. All modern constructors, such as `Promise` and `Map`, must be
called with `new`.
## Message
TypeError: Constructor X requires 'new' (V8-based)
TypeError: Promise constructor cannot be invoked without 'new' (V8-based)
TypeError: calling a builtin X constructor without new is forbidden (Firefox)
TypeError: calling X constructor without new is invalid (Safari)
## Error type
`TypeError`
## What went wrong?
In JavaScript, _calling_ a function without `new` and _constructing_ a
function with `new` are two distinct operations, and functions can behave
differently depending on how they are called.
Apart from the following legacy constructors, all modern constructors must be
called with `new`:
* `Object()`
* `Function()` (and its subclasses)
* `Error()` (and its subclasses)
* `RegExp()`
* `Array()`
Some other constructors, such as `Date()`, and primitive wrappers, such as
`String()`, `Number()`, and `Boolean()`, can also be called with or without
`new`, but the return types differ in the two cases.
On every constructor page, you can find information about whether the
constructor must be called with `new`.
## Examples
### Invalid cases
const m = Map(); // TypeError: calling a builtin Map constructor without new is forbidden
### Valid cases
const m = new Map();
## See also
* `new`
# TypeError: X.prototype.y called on incompatible type
The JavaScript exception "called on incompatible target (or object)" occurs
when a function (on a given object), is called with a `this` not corresponding
to the type expected by the function.
## Message
TypeError: Method Set.prototype.add called on incompatible receiver undefined (V8-based)
TypeError: Bind must be called on a function (V8-based)
TypeError: Illegal invocation (V8-based)
TypeError: Function.prototype.toString requires that 'this' be a Function (V8-based)
TypeError: this is not a Date object. (V8-based)
TypeError: this is not a typed array. (V8-based)
TypeError: Function.prototype.toString called on incompatible object (Firefox)
TypeError: Function.prototype.bind called on incompatible target (Firefox)
TypeError: 'addEventListener' called on an object that does not implement interface EventTarget. (Firefox)
TypeError: Type error (Safari)
TypeError: undefined is not an object (Safari)
## Error type
`TypeError`
## What went wrong?
When this error is thrown, a function (on a given object), is called with a
`this` not corresponding to the type expected by the function.
This issue can arise when using the `Function.prototype.call()` or
`Function.prototype.apply()` methods, and providing a `this` argument which
does not have the expected type.
This issue can also happen when providing a function that is stored as a
property of an object as an argument to another function. In this case, the
object that stores the function won't be the `this` target of that function
when it is called by the other function. To work-around this issue, you will
either need to wrap the callback function in another function, or use the
`Function.prototype.bind()` method to force the `this` argument to the
expected object.
## Examples
### Invalid cases
const mySet = new Set();
["bar", "baz"].forEach(mySet.add);
// mySet.add is a function, but "mySet" is not captured as this.
function myFun() {
console.log(this);
}
["bar", "baz"].forEach(myFun.bind);
// myFun.bind is a function, but "myFun" is not captured as this.
### Valid cases
const mySet = new Set();
["bar", "baz"].forEach(mySet.add.bind(mySet));
// This works due to binding "mySet" as this.
function myFun() {
console.log(this);
}
["bar", "baz"].forEach((x) => myFun.bind(x));
// This works using the "bind" function. It creates a new function forwarding the argument.
## See also
* `Function.prototype.call()`
* `Function.prototype.apply()`
* `Function.prototype.bind()`
# ReferenceError: can't access lexical declaration 'X' before initialization
The JavaScript exception "can't access lexical declaration 'X' before
initialization" occurs when a lexical variable was accessed before it was
initialized. This happens within any scope (global, module, function, or
block) when `let` or `const` variables are accessed before the place where
they are declared is executed.
## Message
ReferenceError: Cannot access 'X' before initialization (V8-based)
ReferenceError: can't access lexical declaration 'X' before initialization (Firefox)
ReferenceError: Cannot access uninitialized variable. (Safari)
## Error type
`ReferenceError`
## What went wrong?
A lexical variable was accessed before it was initialized. This happens within
any scope (global, module, function, or block) when variables declared with
`let` or `const` are accessed before the place where they are declared has
been executed.
Note that it is the execution order of access and variable declaration that
matters, not the order in which the statements appear in the code. For more
information, see the description of Temporal Dead Zone.
This issue does not occur for variables declared using `var`, because they are
initialized with a default value of `undefined` when they are hoisted.
This error can also occur in cyclic imports when a module uses a variable that
depends on the module itself being evaluated.
## Examples
### Invalid cases
In this case, the variable `foo` is accessed before it is declared. At this
point foo has not been initialized with a value, so accessing the variable
throws a reference error.
function test() {
// Accessing the 'const' variable foo before it's declared
console.log(foo); // ReferenceError: foo is not initialized
const foo = 33; // 'foo' is declared and initialized here using the 'const' keyword
}
test();
In this example, the imported variable `a` is accessed but is uninitialized,
because the evaluation of `a.js` is blocked by the evaluation of the current
module `b.js`.
// -- a.js (entry module) --
import { b } from "./b.js";
export const a = 2;
// -- b.js --
import { a } from "./a.js";
console.log(a); // ReferenceError: Cannot access 'a' before initialization
export const b = 1;
### Valid cases
In the following example, we correctly declare a variable using the `const`
keyword before accessing it.
function test() {
// Declaring variable foo
const foo = 33;
console.log(foo); // 33
}
test();
In this example, the imported variable `a` is asynchronously accessed, so both
modules are evaluated before the access to `a` occurs.
// -- a.js (entry module) --
import { b } from "./b.js";
export const a = 2;
// -- b.js --
import { a } from "./a.js";
setTimeout(() => {
console.log(a); // 2
}, 10);
export const b = 1;
## See also
* `let`
* `const`
* `var`
* `class`
# TypeError: can't assign to property "x" on "y": not an object
The JavaScript strict mode exception "can't assign to property" occurs when
attempting to create a property on primitive value such as a symbol, a string,
a number or a boolean. Primitive values cannot hold any property.
## Message
TypeError: Cannot create property 'x' on number '1' (V8-based)
TypeError: can't assign to property "x" on 1: not an object (Firefox)
TypeError: Attempted to assign to readonly property. (Safari)
## Error type
`TypeError`.
## What went wrong?
In strict mode, a `TypeError` is raised when attempting to create a property
on primitive value such as a symbol, a string, a number or a boolean.
Primitive values cannot hold any property.
The problem might be that an unexpected value is flowing at an unexpected
place, or that an object variant of a `String` or a `Number` is expected.
## Examples
### Invalid cases
"use strict";
const foo = "my string";
// The following line does nothing if not in strict mode.
foo.bar = {}; // TypeError: can't assign to property "bar" on "my string": not an object
### Fixing the issue
Either fix the code to prevent the primitive from being used in such places,
or fix the issue by creating the object equivalent `Object`.
"use strict";
const foo = new String("my string");
foo.bar = {};
## See also
* Strict mode
* primitive
# RangeError: x can't be converted to BigInt because it isn't an integer
The JavaScript exception "x can't be converted to BigInt because it isn't an
integer" occurs when the `BigInt()` function is used on a number that isn't an
integer.
## Message
RangeError: The number 1.5 cannot be converted to a BigInt because it is not an integer (V8-based & Firefox)
RangeError: Not an integer (Safari)
## Error type
`RangeError`.
## What went wrong?
When using the `BigInt()` function to convert a number to a BigInt, the number
must be an integer (such that `Number.isInteger` returns true).
## Examples
### Invalid cases
const a = BigInt(1.5);
// RangeError: The number 1.5 cannot be converted to a BigInt because it is not an integer
const b = BigInt(NaN);
// RangeError: NaN cannot be converted to a BigInt because it is not an integer
### Valid cases
const a = BigInt(1);
## See also
* `BigInt()` constructor
* `Number.isInteger()`
# TypeError: can't convert BigInt to number
The JavaScript exception "can't convert BigInt to number" occurs when an
arithmetic operation involves a mix of `BigInt` and `Number` values.
## Message
TypeError: Cannot convert a BigInt value to a number (V8-based)
TypeError: Cannot mix BigInt and other types, use explicit conversions (V8-based)
TypeError: BigInts have no unsigned right shift, use >> instead (V8-based)
TypeError: can't convert BigInt to number (Firefox)
TypeError: Conversion from 'BigInt' to 'number' is not allowed. (Safari)
TypeError: Invalid mix of BigInt and other type in addition/multiplication/…. (Safari)
TypeError: BigInt does not support >>> operator (Safari)
## Error type
`TypeError`.
## What went wrong?
The two sides of an arithmetic operator must both be BigInts or both not. If
an operation involves a mix of BigInts and numbers, it's ambiguous whether the
result should be a BigInt or number, since there may be loss of precision in
both cases.
The error also happens when a BigInt is implicitly converted to a number via
the number coercion process. For example, if a BigInt is passed to a built-in
method that expects a number.
The error can also happen if the unsigned right shift operator (`>>>`) is used
between two BigInts. In Firefox, the message is the same: "can't convert
BigInt to number".
## Examples
### Mixing numbers and BigInts in operations
const sum = 1n + 1;
// TypeError: can't convert BigInt to number
Instead, explicitly coerce one side to a BigInt or number.
const sum = 1n + BigInt(1);
const sum2 = Number(1n) + 1;
### Using unsigned right shift on BigInts
const a = 4n >>> 2n;
// TypeError: can't convert BigInt to number
Use normal right shift instead.
const a = 4n >> 2n;
## See also
* `BigInt`
# TypeError: can't convert x to BigInt
The JavaScript exception "x can't be converted to BigInt" occurs when
attempting to convert a `Symbol`, `null`, or `undefined` value to a `BigInt`,
or if an operation expecting a BigInt parameter receives a number.
## Message
TypeError: Cannot convert null to a BigInt (V8-based)
TypeError: can't convert null to BigInt (Firefox)
TypeError: Invalid argument type in ToBigInt operation (Safari)
## Error type
`TypeError`.
## What went wrong?
When using the `BigInt()` function to convert a value to a BigInt, the value
would first be converted to a primitive. Then, if it's not one of BigInt,
string, number, and boolean, the error is thrown.
Some operations, like `BigInt.asIntN`, require the parameter to be a BigInt.
Passing in a number in this case will also throw this error.
## Examples
### Using BigInt() on invalid values
const a = BigInt(null);
// TypeError: can't convert null to BigInt
const b = BigInt(undefined);
// TypeError: can't convert undefined to BigInt
const c = BigInt(Symbol("1"));
// TypeError: can't convert Symbol("1") to BigInt
const a = BigInt(1);
const b = BigInt(true);
const c = BigInt("1");
const d = BigInt(Symbol("1").description);
**Note:** Simply coercing the value to a string or number using `String()` or
`Number()` before passing it to `BigInt()` is usually not sufficient to avoid
all errors. If the string is not a valid integer number string, a SyntaxError
is thrown; if the number is not an integer (most notably, `NaN`), a RangeError
is thrown. If the range of input is unknown, properly validate it before using
`BigInt()`.
### Passing a number to a function expecting a BigInt
const a = BigInt.asIntN(4, 8);
// TypeError: can't convert 8 to BigInt
const b = new BigInt64Array(3).fill(3);
// TypeError: can't convert 3 to BigInt
const a = BigInt.asIntN(4, 8n);
const b = new BigInt64Array(3).fill(3n);
## See also
* `BigInt()` constructor
# TypeError: can't define property "x": "obj" is not extensible
The JavaScript exception "can't define property "x": "obj" is not extensible"
occurs when `Object.preventExtensions()` marked an object as no longer
extensible, so that it will never have properties beyond the ones it had at
the time it was marked as non-extensible.
## Message
TypeError: Cannot add property x, object is not extensible (V8-based)
TypeError: Cannot define property x, object is not extensible (V8-based)
TypeError: can't define property "x": Object is not extensible (Firefox)
TypeError: Attempting to define property on object that is not extensible. (Safari)
## Error type
`TypeError`
## What went wrong?
Usually, an object is extensible and new properties can be added to it.
However, in this case `Object.preventExtensions()` marked an object as no
longer extensible, so that it will never have properties beyond the ones it
had at the time it was marked as non-extensible.
## Examples
### Adding new properties to a non-extensible objects
In strict mode, attempting to add new properties to a non-extensible object
throws a `TypeError`. In sloppy mode, the addition of the "x" property is
silently ignored.
"use strict";
const obj = {};
Object.preventExtensions(obj);
obj.x = "foo";
// TypeError: can't define property "x": Object is not extensible
In both, strict mode and sloppy mode, a call to `Object.defineProperty()`
throws when adding a new property to a non-extensible object.
const obj = {};
Object.preventExtensions(obj);
Object.defineProperty(obj, "x", { value: "foo" });
// TypeError: can't define property "x": Object is not extensible
To fix this error, you will either need to remove the call to
`Object.preventExtensions()` entirely, or move it to a position so that the
property is added earlier and only later the object is marked as non-
extensible. Of course you can also remove the property that was attempted to
be added, if you don't need it.
"use strict";
const obj = {};
obj.x = "foo"; // add property first and only then prevent extensions
Object.preventExtensions(obj);
## See also
* `Object.preventExtensions()`
# TypeError: property "x" is non-configurable and can't be deleted
The JavaScript exception "property is non-configurable and can't be deleted"
occurs when it was attempted to delete a property, but that property is non-
configurable.
## Message
TypeError: Cannot delete property 'x' of #