# 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 # (V8-based) TypeError: property "x" is non-configurable and can't be deleted (Firefox) TypeError: Unable to delete property. (Safari) ## Error type `TypeError` in strict mode only. ## What went wrong? It was attempted to delete a property, but that property is non-configurable. The `configurable` attribute controls whether the property can be deleted from the object and whether its attributes (other than `writable`) can be changed. This error happens only in strict mode code. In non-strict code, the operation returns `false`. ## Examples ### Attempting to delete non-configurable properties Non-configurable properties are not super common, but they can be created using `Object.defineProperty()` or `Object.freeze()`. "use strict"; const obj = Object.freeze({ name: "Elsa", score: 157 }); delete obj.score; // TypeError "use strict"; const obj = {}; Object.defineProperty(obj, "foo", { value: 2, configurable: false }); delete obj.foo; // TypeError "use strict"; const frozenArray = Object.freeze([0, 1, 2]); frozenArray.pop(); // TypeError There are also a few non-configurable properties built into JavaScript. Maybe you tried to delete a mathematical constant. "use strict"; delete Math.PI; // TypeError ## See also * `delete` * `Object.defineProperty()` * `Object.freeze()` # SyntaxError: private fields can't be deleted The JavaScript exception "SyntaxError: private fields can't be deleted" occurs when `delete` is used on a private property of a class or an object. ## Message SyntaxError: Private fields can not be deleted (V8-based) SyntaxError: private fields can't be deleted (Firefox) SyntaxError: Cannot delete private field X (Safari) ## Error type `SyntaxError` ## What went wrong? There's code trying to `delete` a private property (field or method) of an object or a class. This is forbidden by JavaScript—private properties cannot be added or removed on the fly. ## Examples class MyClass { #myPrivateField; deleteIt() { delete this.#myPrivateField; // SyntaxError: private fields can't be deleted } } class MyClass { #myPrivateMethod() { } #deleteIt() { delete this.#myPrivateMethod; // SyntaxError: private fields can't be deleted } } ## See also * Classes * Private properties # TypeError: can't redefine non-configurable property "x" The JavaScript exception "can't redefine non-configurable property" occurs when it was attempted to redefine a property, but that property is non- configurable. ## Message TypeError: Cannot redefine property: "x" (V8-based) TypeError: can't redefine non-configurable property "x" (Firefox) TypeError: Attempting to change value of a readonly property. (Safari) ## Error type `TypeError` ## What went wrong? It was attempted to redefine a property, but that property is non- configurable. The `configurable` attribute controls whether the property can be deleted from the object and whether its attributes (other than `writable`) can be changed. Usually, properties in an object created by an object initializer are configurable. However, for example, when using `Object.defineProperty()`, the property isn't configurable by default. ## Examples ### Non-configurable properties created by Object.defineProperty The `Object.defineProperty()` creates non-configurable properties if you haven't specified them as configurable. const obj = Object.create({}); Object.defineProperty(obj, "foo", { value: "bar" }); Object.defineProperty(obj, "foo", { value: "baz" }); // TypeError: can't redefine non-configurable property "foo" You will need to set the "foo" property to configurable, if you intend to redefine it later in the code. const obj = Object.create({}); Object.defineProperty(obj, "foo", { value: "bar", configurable: true }); Object.defineProperty(obj, "foo", { value: "baz", configurable: true }); ## See also * [[Configurable]] * `Object.defineProperty()` # TypeError: can't set prototype of this object The JavaScript exception "can't set prototype of this object" occurs when attempting to set the prototype of an object, but the object's prototype is frozen, either by being a built-in immutable prototype object, or by being non-extensible. ## Message TypeError: Immutable prototype object 'Object.prototype' cannot have their prototype set (V8-based) TypeError: # is not extensible (V8-based) TypeError: can't set prototype of this object (Firefox) TypeError: Cannot set prototype of immutable prototype object (Safari) TypeError: Attempted to assign to readonly property. (Safari) ## Error type `TypeError` ## What went wrong? You are using one of the prototype-mutating methods—most notably, `Object.setPrototypeOf()`—on an object whose prototype is immutable. Some built-in objects have immutable prototypes, such as `Object.prototype` and `window`, for security reasons. User objects can also prevent prototype changes by using `Object.preventExtensions()`, `Object.seal()`, or `Object.freeze()`. ## Examples ### Changing the prototype of a built-in object A selected few built-in objects have immutable prototypes. For example, you cannot change the prototype of `Object.prototype`: Object.setPrototypeOf(Object.prototype, {}); This prevents you from being able to arbitrarily change the behavior of all objects in the system. The prototype of `Object.prototype` is always `null`. However, other built-in prototype objects, such as `Function.prototype` and `Array.prototype`, are not protected by default in this regard. ### Changing the prototype of a non-extensible object If you make an object non-extensible, you cannot change its prototype either: const obj = {}; Object.preventExtensions(obj); Object.setPrototypeOf(obj, {}); // TypeError: can't set prototype of this object ## See also * `Object.setPrototypeOf()` * `Object.preventExtensions()` # SyntaxError: cannot use `??` unparenthesized within `||` and `&&` expressions The JavaScript exception "cannot use `??` unparenthesized within `||` and `&&` expressions" occurs when an nullish coalescing operator is used with a logical OR or logical AND in the same expression without parentheses. ## Message SyntaxError: Unexpected token '??' (V8-based) SyntaxError: cannot use `??` unparenthesized within `||` and `&&` expressions (Firefox) SyntaxError: Unexpected token '??'. Coalescing and logical operators used together in the same expression; parentheses must be used to disambiguate. (Safari) ## Error type `SyntaxError` ## What went wrong? The operator precedence chain looks like this: | > && > || > = | > ?? > = However, the precedence _between_ `??` and `&&`/`||` is intentionally undefined, because the short circuiting behavior of logical operators can make the expression's evaluation counter-intuitive. Therefore, the following combinations are all syntax errors, because the language doesn't know how to parenthesize the operands: a ?? b || c; a || b ?? c; a ?? b && c; a && b ?? c; Instead, make your intent clear by parenthesizing either side explicitly: (a ?? b) || c; a ?? (b && c); ## Examples When migrating legacy code that uses `||` and `&&` for guarding against `null` or `undefined`, you may often convert it partially: function getId(user, fallback) { // Previously: user && user.id || fallback return user && user.id ?? fallback; // SyntaxError: cannot use `??` unparenthesized within `||` and `&&` expressions } Instead, consider parenthesizing the `&&`: function getId(user, fallback) { return (user && user.id) ?? fallback; } Even better, consider using optional chaining instead of `&&`: function getId(user, fallback) { return user?.id ?? fallback; } ## See also * Issue about nullish coalescing precedence in the TC39 nullish-coalescing proposal * Nullish coalescing operator (`??`) * Operator precedence # TypeError: class constructors must be invoked with 'new' The JavaScript exception "class constructors must be invoked with 'new'" occurs when a class constructor is called without the `new` keyword. All class constructors must be called with `new`. ## Message TypeError: Class constructor X cannot be invoked without 'new' (V8-based) TypeError: Class constructors cannot be invoked without 'new' (V8-based) TypeError: class constructors must be invoked with 'new' (Firefox) TypeError: Cannot call a class constructor without |new| (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. Traditionally, JavaScript functions have been used as both constructors and normal functions, and can detect how they were called using `new.target`. However, class constructors are always constructors and cannot be called as normal functions. ## Examples ### Invalid cases class X {} X(); // TypeError: class constructors must be invoked with 'new' ### Valid cases class X {} new X(); ## See also * Classes * `new` # TypeError: Iterator/AsyncIterator constructor can't be used directly The JavaScript exception "Iterator constructor can't be used directly" or "AsyncIterator constructor can't be used directly" occurs when you try to use the `Iterator()` or `AsyncIterator()` constructors directly to create instances. These constructors are _abstract classes_ and should only be inherited from. ## Message TypeError: Abstract class Iterator not directly constructable (V8-based) TypeError: Iterator constructor can't be used directly (Firefox) TypeError: Iterator cannot be constructed directly (Safari) TypeError: Abstract class AsyncIterator not directly constructable (V8-based) TypeError: AsyncIterator constructor can't be used directly (Firefox) TypeError: AsyncIterator cannot be constructed directly (Safari) ## Error type `TypeError` ## What went wrong? The `Iterator` and `AsyncIterator` constructors are abstract classes and should not be used directly. They check the value of `new.target` and throw if it is the same as the constructor itself. The only way to use these constructors is to inherit from them in a subclass and call `super()` in the subclass constructor. The subclass must also define a `next()` method to be useful. ## Examples ### Invalid cases new Iterator(); ### Valid cases class MyIterator extends Iterator { #step; #end; constructor(start, end) { // Implicitly calls new Iterator(), but with a different `new.target` super(); this.#step = start; this.#end = end; } next() { if (this.#step >= this.#end) { return { done: true }; } return { value: this.#step++, done: false }; } } new MyIterator(); ## See also * `AsyncIterator` * `Iterator` # TypeError: cyclic object value The JavaScript exception "cyclic object value" occurs when object references were found in JSON. `JSON.stringify()` doesn't try to solve them and fails accordingly. ## Message TypeError: Converting circular structure to JSON (V8-based) TypeError: cyclic object value (Firefox) TypeError: JSON.stringify cannot serialize cyclic structures. (Safari) ## Error type `TypeError` ## What went wrong? The JSON format per se doesn't support object references (although an IETF draft exists), hence `JSON.stringify()` doesn't try to solve them and fails accordingly. ## Examples ### Circular references In a circular structure like the following: const circularReference = { otherData: 123 }; circularReference.myself = circularReference; `JSON.stringify()` will fail JSON.stringify(circularReference); // TypeError: cyclic object value To serialize circular references you can use a library that supports them (e.g., cycle.js) or implement a solution by yourself, which will require finding and replacing (or removing) the cyclic references by serializable values. The snippet below illustrates how to find and filter (thus causing data loss) a cyclic reference by using the `replacer` parameter of `JSON.stringify()`: function getCircularReplacer() { const ancestors = []; return function (key, value) { if (typeof value !== "object" || value === null) { return value; } // `this` is the object that value is contained in, // i.e., its direct parent. while (ancestors.length > 0 && ancestors.at(-1) !== this) { ancestors.pop(); } if (ancestors.includes(value)) { return "[Circular]"; } ancestors.push(value); return value; }; } JSON.stringify(circularReference, getCircularReplacer()); // {"otherData":123,"myself":"[Circular]"} const o = {}; const notCircularReference = [o, o]; JSON.stringify(notCircularReference, getCircularReplacer()); // [{},{}] ## See also * `JSON.stringify()` * cycle.js on GitHub # TypeError: can't set prototype: it would cause a prototype chain cycle The JavaScript exception "TypeError: can't set prototype: it would cause a prototype chain cycle" occurs when an object's prototype is set to an object such that the prototype chain becomes circular (`a` and `b` both have each other in their prototype chains). ## Message TypeError: Cyclic __proto__ value (V8-based) TypeError: can't set prototype: it would cause a prototype chain cycle (Firefox) TypeError: cyclic __proto__ value (Safari) ## Error type `TypeError` ## What went wrong? A loop, also called a cycle, was introduced in a prototype chain. That means that when walking this prototype chain, the same place would be accessed over and over again, instead of eventually reaching `null`. This error is thrown at the time of setting the prototype. In an operation like `Object.setPrototypeOf(a, b)`, if `a` already exists in the prototype chain of `b`, this error will be thrown. ## Examples const a = {}; Object.setPrototypeOf(a, a); // TypeError: can't set prototype: it would cause a prototype chain cycle const a = {}; const b = {}; const c = {}; Object.setPrototypeOf(a, b); Object.setPrototypeOf(b, c); Object.setPrototypeOf(c, a); // TypeError: can't set prototype: it would cause a prototype chain cycle ## See also * Object Prototypes * Inheritance and the prototype chain # SyntaxError: applying the 'delete' operator to an unqualified name is deprecated The JavaScript strict mode-only exception "applying the 'delete' operator to an unqualified name is deprecated" occurs when variables are attempted to be deleted using the `delete` operator. ## Message SyntaxError: Delete of an unqualified identifier in strict mode. (V8-based) SyntaxError: applying the 'delete' operator to an unqualified name is deprecated (Firefox) SyntaxError: Cannot delete unqualified property 'a' in strict mode. (Safari) ## Error type `SyntaxError` in strict mode only. ## What went wrong? Normal variables in JavaScript can't be deleted using the `delete` operator. In strict mode, an attempt to delete a variable will throw an error and is not allowed. The `delete` operator can only delete properties on an object. Object properties are "qualified" if they are configurable. Unlike what common belief suggests, the `delete` operator has **nothing** to do with directly freeing memory. Memory management is done indirectly via breaking references, see the memory management page and the `delete` operator page for more details. This error only happens in strict mode code. In non-strict code, the operation just returns `false`. ## Examples ### Freeing the contents of a variable Attempting to delete a plain variable throws an error in strict mode: "use strict"; var x; // … delete x; // SyntaxError: applying the 'delete' operator to an unqualified name // is deprecated To free the contents of a variable, you can set it to `null`: "use strict"; var x; // … x = null; // x can be garbage collected ## See also * `delete` * Memory management * TypeError: property "x" is non-configurable and can't be deleted # TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed The JavaScript strict mode-only exception "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them" occurs when the deprecated `arguments.callee`, `Function.prototype.caller`, or `Function.prototype.arguments` properties are used. ## Message TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them (V8-based & Firefox) TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context. (Safari) ## Error type `TypeError` in strict mode only. ## What went wrong? In strict mode, the `arguments.callee`, `Function.prototype.caller`, or `Function.prototype.arguments` properties are used and shouldn't be. They are deprecated, because they leak the function caller, are non-standard, hard to optimize and potentially a performance-harmful feature. ## Examples ### Deprecated function.caller or arguments.callee `Function.prototype.caller` and `arguments.callee` are deprecated (see the reference articles for more information). "use strict"; function myFunc() { if (myFunc.caller === null) { return "The function was called from the top!"; } return `This function's caller was ${myFunc.caller}`; } myFunc(); // TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them ### Function.prototype.arguments `Function.prototype.arguments` is deprecated (see the reference article for more information). "use strict"; function f(n) { g(n - 1); } function g(n) { console.log(`before: ${g.arguments[0]}`); if (n > 0) { f(n); } console.log(`after: ${g.arguments[0]}`); } f(2); console.log(`returned: ${g.arguments}`); // TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them ## See also * Deprecated and obsolete features * Strict mode * `Function.prototype.arguments` * `Function.prototype.caller` * `arguments.callee` # SyntaxError: octal escape sequences can't be used in untagged template literals or in strict mode code The JavaScript exception "octal escape sequences can't be used in untagged template literals or in strict mode code" occurs when octal escape sequences are used in strict mode string literals or untagged template literals. ## Message SyntaxError: Octal escape sequences are not allowed in strict mode. (V8-based) SyntaxError: \8 and \9 are not allowed in strict mode. (V8-based) SyntaxError: Octal escape sequences are not allowed in template strings. (V8-based) SyntaxError: \8 and \9 are not allowed in template strings. (V8-based) SyntaxError: octal escape sequences can't be used in untagged template literals or in strict mode code (Firefox) SyntaxError: the escapes \8 and \9 can't be used in untagged template literals or in strict mode code (Firefox) SyntaxError: The only valid numeric escape in strict mode is '\0' (Safari) ## Error type `SyntaxError` ## What went wrong? The string escape sequence of the form `\` followed by any number of digits, except a single `0`, is deprecated. If you want to represent a character by its code point value, you should use the `\x` or `\u` escape sequence instead, such as `\x01` or `\u0001` instead of `\1`. Untagged template literals are never allowed to contain octal escape sequences, whether in strict mode or not. However, _tagged_ template literals can contain any form of escape sequence, and will cause the template array received by the tag function to contain `undefined`. ## Examples ### Octal escape sequences "use strict"; "\251"; // SyntaxError: octal escape sequences can't be used in untagged template literals or in strict mode code ### Valid octal numbers For octal escape sequences, you can use hexadecimal escape sequences instead: "\xA9"; If you want to represent some source text literally without interpreting any escape sequence, use `String.raw`: String.raw`\251`; // A string containing four characters ## See also * Lexical grammar # SyntaxError: "0"-prefixed octal literals are deprecated The JavaScript strict mode-only exception "0-prefixed octal literals are deprecated; use the "0o" prefix instead" occurs when deprecated octal literals (`0` followed by digits) are used. ## Message SyntaxError: Octal literals are not allowed in strict mode. (V8-based) SyntaxError: Decimals with leading zeros are not allowed in strict mode. (V8-based) SyntaxError: Unexpected number (V8-based) SyntaxError: "0"-prefixed octal literals are deprecated; use the "0o" prefix instead (Firefox) SyntaxError: Decimal integer literals with a leading zero are forbidden in strict mode (Safari) ## Error type `SyntaxError` in strict mode only. ## What went wrong? Octal literals are deprecated. When you prefix a decimal integer with `0`, you actually change it to an octal literal, which may be surprising. The standardized syntax uses a leading zero followed by a lowercase or uppercase Latin letter "O" (`0o` or `0O`). Leading zeros are always forbidden, even when the literal is not valid octal literal syntax (such as when the literal contains the digits `8` or `9`, or it has a decimal point). A number literal may only start with `0` if that 0 is its units place. ## Examples ### "0"-prefixed octal literals "use strict"; 03; // SyntaxError: "0"-prefixed octal literals are deprecated; use the "0o" prefix instead ### Valid octal numbers Use a leading zero followed by the letter "o" or "O": 0o3; ## See also * Lexical grammar # SyntaxError: Using //@ to indicate sourceURL pragmas is deprecated. Use //# instead The JavaScript warning "Using `//@` to indicate sourceURL pragmas is deprecated. Use `//#` instead" occurs when there is a deprecated source map syntax in a JavaScript source. ## Message Warning: SyntaxError: Using //@ to indicate sourceURL pragmas is deprecated. Use //# instead Warning: SyntaxError: Using //@ to indicate sourceMappingURL pragmas is deprecated. Use //# instead ## Error type A warning that a `SyntaxError` occurred. JavaScript execution won't be halted. ## What went wrong? There is a deprecated source map syntax in a 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. The source map specification changed the syntax due to a conflict with IE whenever it was found in the page after `//@cc_on` was interpreted to turn on conditional compilation in the IE JScript engine. The conditional compilation comment in IE is a little known feature, but it broke source maps with jQuery and other libraries. ## Examples ### Deprecated syntax Syntax with the "@" sign is deprecated. //@ sourceMappingURL=http://example.com/path/to/your/sourcemap.map ### Standard syntax Use the "#" sign instead. //# sourceMappingURL=http://example.com/path/to/your/sourcemap.map Or, alternatively, you can set a `SourceMap` header to your JavaScript file to avoid having a comment at all: 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) * `SourceMap` # SyntaxError: duplicate formal argument x The JavaScript exception "duplicate formal argument x" or "duplicate argument names not allowed in this context" occurs when a function creates two or more parameter bindings with the same name, and the function is not a non-strict function with only simple parameters. ## Message SyntaxError: Duplicate parameter name not allowed in this context (V8-based) SyntaxError: duplicate formal argument x (Firefox) SyntaxError: duplicate argument names not allowed in this context (Firefox) SyntaxError: Cannot declare a parameter named 'x' in strict mode as it has already been declared. (Safari) SyntaxError: Duplicate parameter 'x' not allowed in function with default parameter values. (Safari) SyntaxError: Duplicate parameter 'x' not allowed in function with a rest parameter. (Safari) SyntaxError: Duplicate parameter 'x' not allowed in function with destructuring parameters. (Safari) ## Error type `SyntaxError` ## What went wrong? Having two formal parameters of the same name is likely a mistake—the second occurrence would cause the first occurrence to be inaccessible through the parameter name. In legacy JavaScript, this was allowed. Therefore, to not break existing code, this is only an error if the code is guaranteed to not be legacy—either because it is in strict mode or it uses modern parameter syntax (rest, default, or destructured parameters). ## Examples ### Invalid cases "use strict"; function add(x, x) { // How can you access both "x" parameters? // SyntaxError: duplicate formal argument x } function doSomething(name, { name }) { // How can you access both "name" parameters? // SyntaxError: duplicate argument names not allowed in this context } ### Valid cases function doSomething(operationName, { name: userName }) { // You can access both "operationName" and "userName" parameters. } function doSomething(name, user) { // You can access both "name" and "user.name" parameters. } ## See also * Functions * Strict mode # SyntaxError: property name __proto__ appears more than once in object literal The JavaScript exception "property name __proto__ appears more than once in object literal" occurs when an object literal contains multiple occurrences of the `__proto__` field, which is used to set the prototype of this new object. ## Message SyntaxError: Duplicate __proto__ fields are not allowed in object literals (V8-based) SyntaxError: property name __proto__ appears more than once in object literal (Firefox) SyntaxError: Attempted to redefine __proto__ property. (Safari) ## Error type `SyntaxError` ## What went wrong? The `__proto__` key, unlike other property keys, is a special syntax in an object literal. It is used to set the prototype of the object being created and is not allowed to appear more than once in an object literal. Note that this restriction only applies to the `__proto__` prototype setter syntax: if it actually has the effect of creating a property called `__proto__`, then it can appear multiple times. See prototype setter for the exact syntax restrictions. Worth noting that the `__proto__` key in object literals is a special syntax and is not deprecated, unlike the `Object.prototype.__proto__` accessor property. ## Examples ### Invalid cases const obj = { __proto__: {}, __proto__: { a: 1 } }; ### Valid cases // Only setting the prototype once const obj = { __proto__: { a: 1 } }; // These syntaxes all create a property called "__proto__" and can coexist // They would overwrite each other and the last one is actually used const __proto__ = null; const obj2 = { ["__proto__"]: {}, __proto__, __proto__() {}, get __proto__() { return 1; }, }; ## See also * Object initializer * Inheritance and the prototype chain # SyntaxError: getter and setter for private name #x should either be both static or non-static The JavaScript exception "mismatched placement" occurs when a private getter and setter are mismatched in whether or not they are `static`. ## Message SyntaxError: Identifier '#x' has already been declared (V8-based) SyntaxError: getter and setter for private name #x should either be both static or non-static (Firefox) SyntaxError: Cannot declare a private non-static getter if there is a static private setter with used name. (Safari) ## Error type `SyntaxError` ## What went wrong? Private getters and setters for the same name must either be both `static`, or both non-static. This limitation does not exist for public methods. ## Examples ### Mismatched placement class Test { static set #foo(_) {} get #foo() {} } // SyntaxError: getter and setter for private name #foo should either be both static or non-static Since `foo` is private, the methods must be either both `static`: class Test { static set #foo(_) {} static get #foo() {} } or non-static: class Test { set #foo(_) {} get #foo() {} } ## See also * `get` * `set` * `static` * Private properties # RangeError: form must be one of 'NFC', 'NFD', 'NFKC', or 'NFKD' The JavaScript exception "form must be one of 'NFC', 'NFD', 'NFKC', or 'NFKD'" occurs when an unrecognized string is passed to the `String.prototype.normalize()` method. ## Message RangeError: The normalization form should be one of NFC, NFD, NFKC, NFKD. (V8-based) RangeError: form must be one of 'NFC', 'NFD', 'NFKC', or 'NFKD' (Firefox) RangeError: argument does not match any normalization form (Safari) ## Error type `RangeError` ## What went wrong? The `String.prototype.normalize()` method only accepts the following four values as its `form` argument: `"NFC"`, `"NFD"`, `"NFKC"`, or `"NFKD"`. If you pass any other value, an error will be thrown. Read the reference of `normalize()` to learn about different normalization forms. ## Examples ### Invalid cases "foo".normalize("nfc"); // RangeError "foo".normalize(" NFC "); // RangeError ### Valid cases "foo".normalize("NFC"); // 'foo' ## See also * `String.prototype.normalize()` # SyntaxError: functions cannot be labelled The JavaScript exception "functions cannot be labelled" occurs when a `function` declaration has a label before it. ## Message SyntaxError: In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement. (V8-based) SyntaxError: In strict mode code, functions can only be declared at top level or inside a block. (V8-based) SyntaxError: Generators can only be declared at the top level or inside a block. (V8-based) SyntaxError: Async functions can only be declared at the top level or inside a block. (V8-based) SyntaxError: functions can only be labelled inside blocks (Firefox) SyntaxError: functions cannot be labelled (Firefox) SyntaxError: generator functions cannot be labelled (Firefox) SyntaxError: async function declarations can't appear in single-statement context (Firefox) SyntaxError: Unexpected keyword 'function'. Function declarations are only allowed inside block statements or at the top level of a program. (Safari) SyntaxError: Function declarations are only allowed inside blocks or switch statements in strict mode. (Safari) SyntaxError: Unexpected token '*'. Cannot use generator function declaration in single-statement context. (Safari) SyntaxError: Unexpected keyword 'function'. Cannot use async function declaration in single-statement context. (Safari) ## Error type `SyntaxError` ## What went wrong? Function declarations are never supposed to be labeled, because labels should only apply to statements, not declarations. There's no way to actually jump to this label. However, due to some legacy JavaScript syntax rules, the error condition is a bit more complicated than necessary: * In strict mode, function declarations are never allowed to be labeled. * In non-strict mode, function declarations are allowed to be labeled, but not when the function is the sole statement of an `if` statement (which itself is a deprecated feature). * Async functions, generator functions, and async generator functions are never allowed to be labeled. The error message may say something along the lines of "invalid place for a function declaration to appear", because when the parser sees a label, it expects a statement to follow, and a function declaration is not a statement. It depends on whether the error's perspective is that a label cannot be followed by a function, or that a function cannot be preceded by a label. ## Examples ### Misparsed object literal While it's possible that you actually expect the label to do _something_ along the lines of being a jump target, usually you didn't intend for it to be a label. The most common case is you actually want it to be a property key in an object literal: const createObj = () => { greet: function greet() { // SyntaxError: functions cannot be labelled console.log("Hello"); } }; Here, `{...}` is actually not an object literal, but is instead the block body of the arrow function, so `greet:` becomes a label. To fix this, you need to wrap the object literal in parentheses: const createObj = () => ({ greet: function greet() { console.log("Hello"); }, }); You may also want to use the method syntax for object literals, which avoids this pitfall: const createObj = () => ({ greet() { console.log("Hello"); }, }); ## See also * Labeled statement * `function` * Strict mode * Deprecated and obsolete features # TypeError: can't access/set private field or method: object is not the right class The JavaScript exception "can't access private field or method: object is not the right class" or "can't set private field: object is not the right class" occurs when a private field or method is get or set on an object that does not have this private property defined. ## Message TypeError: Cannot read private member #x from an object whose class did not declare it (V8-based) TypeError: Cannot write private member #x to an object whose class did not declare it (V8-based) TypeError: can't access private field or method: object is not the right class (Firefox) TypeError: can't set private field: object is not the right class (Firefox) TypeError: Cannot access invalid private field (evaluating 'this.#x') (Safari) ## Error type `TypeError` ## What went wrong? You are trying to get or set a private field or method on an object, but that object does not contain this private property. Private instance properties can only be accessed on instances of the class (including its subclasses) that declares them; private static properties can only be accessed on the class itself that declares them, and not on subclasses. This error occurs when the private name exists in the class scope but the object it's accessed on is invalid, If the private name does not exist, you will get a syntax error instead. ## Examples ### Mismatched static/instance fields You may have declared the field as a static field, but are trying to access it on an instance, or vice versa. class MyClass { static #x = 0; doSomething() { console.log(this.#x); } } const obj = new MyClass(); obj.doSomething(); // TypeError: can't access private field: object is not the right class To fix this, either change the field to be an instance field, or access the field on the class itself, or declare another field on the instance. Note that the private namespace is shared between static and instance properties, so you cannot have a static and instance private property with the same name. class MyClass { #x = 0; doSomething() { console.log(this.#x); } } class MyClass2 { static #x = 0; doSomething() { console.log(MyClass2.#x); } } ### Wrong object used Perhaps you have a method that access `this.#x`, but it is called with another `this` value. class JSONReplacer { #count = 0; func(key, value) { if (typeof value === "object") { this.#count++; } return value; } } JSON.stringify({ a: 1, b: { c: 2 } }, new JSONReplacer().func); // TypeError: can't access private field: object is not the right class This is because `JSON.stringify()` calls the replacer function with the object containing `value` as `this`, so the private field is not accessible. To fix this, you can bind the method to the object, or use an arrow function, to ensure that `replacer.func` is called with the correct `this` value. const replacer = new JSONReplacer(); JSON.stringify({ a: 1, b: { c: 2 } }, replacer.func.bind(replacer)); JSON.stringify({ a: 1, b: { c: 2 } }, (...args) => replacer.func(...args)); Most of the time, if you accidentally unbound a method, the method would be called with `undefined` as `this`, which would result in a different error (TypeError: can't convert undefined to object). This error only occurs when the method is called with a different object as `this`, either by using `call()` or `apply()`, or by passing the method as a callback to a function that calls it with a different `this` value. If you don't know for sure that the object will contain the private property, as in the following code: class MyClass { #x = 0; static doSomething(obj) { console.log(obj.#x); // Throws if obj is not an instance of MyClass } } You can use the `in` operator to perform a _branded check_ first. class MyClass { #x = 0; static doSomething(obj) { if (!(#x in obj)) { return; } console.log(obj.#x); } } ### Accessing static properties on subclasses If you have a private static property, you can only access it on the class that declares it, not on subclasses. class MyClass { static #x = 0; doSomething() { console.log(this.#x); } } class MySubClass extends MyClass {} MySubClass.doSomething(); // TypeError: can't access private field: object is not the right class To fix this, never access private static properties through `this`. Instead, always explicitly specify the class's name. class MyClass { static #x = 0; doSomething() { console.log(MyClass.#x); } } ### Accessing same-name private properties on another class Unlike normal string or symbol properties, private names are not shared between classes. If you have a private property with the same name in two classes, they are still not the same property, and you cannot access one class's private property from another class. class MyClass { #x = 0; } class MyOtherClass { #x = 1; doSomething(o) { console.log(o.#x); } } const obj = new MyClass(); new MyOtherClass().doSomething(obj); // TypeError: can't access private field: object is not the right class ### Adding private properties to unrelated objects You cannot dynamically _add_ private properties to unrelated objects. class MyClass { #x = 0; static stamp(obj) { obj.#x = 1; } } MyClass.stamp({}); // TypeError: can't set private field: object is not the right class If you really want to do this, consider the return override trick. However, in general, you would probably want to use a `WeakMap` instead. class MyClass { static #objToX = new WeakMap(); static stamp(obj) { MyClass.#objToX.set(obj, 1); } } MyClass.stamp({}); ## See also * Classes * Private properties # SyntaxError: getter functions must have no arguments The JavaScript exception "getter functions must have no arguments" occurs when a getter is declared and the parameter list is non-empty. ## Message SyntaxError: Getter must not have any formal parameters. (V8-based) SyntaxError: getter functions must have no arguments (Firefox) SyntaxError: Unexpected identifier 'x'. getter functions must have no parameters. (Safari) ## Error type `SyntaxError` ## What went wrong? The `get` property syntax looks like a function, but it is stricter and not all function syntax is allowed. A getter is always invoked with no arguments, so defining it with any parameter is likely an error. Note that this error only applies to property getters using the `get` syntax. If you define the getter using `Object.defineProperty()`, etc., the getter is defined as a normal function, although it's likely still an error if the getter expects any arguments, as it will be called without any. ## Examples ### Invalid cases const obj = { get value(type) { return type === "string" ? String(Math.random()) : Math.random(); }, }; ### Valid cases // Remove the parameter const obj = { get value() { return Math.random(); }, }; // Use a normal method, if you need a parameter const obj = { getValue(type) { return type === "string" ? String(Math.random()) : Math.random(); }, }; ## See also * Functions * `get` # TypeError: setting getter-only property "x" The JavaScript strict mode-only exception "setting getter-only property" occurs when there is an attempt to set a new value to a property for which only a getter is specified, or when setting a private property that similarly only has a getter defined. ## Message TypeError: Cannot set property x of # which has only a getter (V8-based) TypeError: '#x' was defined without a setter (V8-based) TypeError: setting getter-only property "x" (Firefox) TypeError: Attempted to assign to readonly property. (Safari) TypeError: Trying to access an undefined private setter (Safari) ## Error type `TypeError` in strict mode only. ## What went wrong? There is an attempt to set a new value to a property for which only a getter is specified. While this will be silently ignored in non-strict mode, it will throw a `TypeError` in strict mode. Classes are always in strict mode, so assigning to a getter-only private property always throws this error. ## Examples ### Property with no setter The example below shows how to set a getter for a property. It doesn't specify a setter, so a `TypeError` will be thrown upon trying to set the `temperature` property to `30`. For more details see also the `Object.defineProperty()` page. "use strict"; function Archiver() { const temperature = null; Object.defineProperty(this, "temperature", { get() { console.log("get!"); return temperature; }, }); } const arc = new Archiver(); arc.temperature; // 'get!' arc.temperature = 30; // TypeError: setting getter-only property "temperature" To fix this error, you will either need to remove the `arc.temperature = 30` line, which attempts to set the temperature property, or you will need to implement a setter for it, for example like this: "use strict"; function Archiver() { let temperature = null; const archive = []; Object.defineProperty(this, "temperature", { get() { console.log("get!"); return temperature; }, set(value) { temperature = value; archive.push({ val: temperature }); }, }); this.getArchive = function () { return archive; }; } const arc = new Archiver(); arc.temperature; // 'get!' arc.temperature = 11; arc.temperature = 13; arc.getArchive(); // [{ val: 11 }, { val: 13 }] ## See also * `Object.defineProperty()` * `Object.defineProperties()` # SyntaxError: Unexpected '#' used outside of class body The JavaScript exception "Unexpected '#' used outside of class body" occurs when a hash ("#") is encountered in an unexpected context, most notably outside of a class declaration. Hashes are valid at the beginning of a file as a hashbang comment, or inside of a class as part of a private field. You may encounter this error if you forget the quotation marks when trying to access a DOM identifier as well. ## Message SyntaxError: Unexpected '#' used outside of class body. ## Error type `SyntaxError` ## What went wrong? We encountered a `#` somewhere unexpected. This may be due to code moving around and no longer being part of a class, a hashbang comment found on a line other than the first line of a file, or accidentally forgetting the quotation marks around a DOM identifier. ## Examples ### Missing quotation marks For each case, there might be something slightly wrong. For example document.querySelector(#some-element) This can be fixed via document.querySelector("#some-element"); ### Outside of a class class ClassWithPrivateField { #privateField; constructor() {} } this.#privateField = 42; This can be fixed by moving the private field back into the class class ClassWithPrivateField { #privateField; constructor() { this.#privateField = 42; } } ## See also * `SyntaxError` # SyntaxError: identifier starts immediately after numeric literal The JavaScript exception "identifier starts immediately after numeric literal" occurs when an identifier started with a digit. Identifiers can only start with a letter, underscore (_), or dollar sign ($). ## Message SyntaxError: Invalid or unexpected token (V8-based) SyntaxError: identifier starts immediately after numeric literal (Firefox) SyntaxError: No identifiers allowed directly after numeric literal (Safari) ## Error type `SyntaxError` ## What went wrong? The names of variables, called identifiers, conform to certain rules, which your code must adhere to! A JavaScript identifier must start with a letter, underscore (_), or dollar sign ($). They can't start with a digit! Only subsequent characters can be digits (0-9). ## Examples ### Variable names starting with numeric literals Variable names can't start with numbers in JavaScript. The following fails: const 1life = "foo"; // SyntaxError: identifier starts immediately after numeric literal const foo = 1life; // SyntaxError: identifier starts immediately after numeric literal You will need to rename your variable to avoid the leading number. const life1 = "foo"; const foo = life1; In JavaScript, there is a syntactic peculiarity when calling properties or methods on numbers. If you want to call a method on an integer, you cannot immediately use a dot after the number because the dot is interpreted as the start of a decimal fraction, causing the parser to see the method's name as an identifier immediately after a number literal. To avoid this, you need to either wrap the number in parentheses or use a double dot, where the first dot is a decimal point for the number literal and the second dot is the property accessor. alert(typeof 1.toString()) // SyntaxError: identifier starts immediately after numeric literal Correct ways to call methods on numbers: // Wrap the number in parentheses alert(typeof (1).toString()); // Add an extra dot for the number literal alert(typeof 2..toString()); // Use square brackets alert(typeof 3["toString"]()); ## See also * Lexical grammar * Grammar and types guide # SyntaxError: illegal character The JavaScript exception "illegal character" occurs when the lexer reads a character that's not part of a string literal, and the character cannot constitute a valid token in the language. ## Message SyntaxError: Invalid or unexpected token (V8-based) SyntaxError: illegal character U+201C (Firefox) SyntaxError: Invalid character '\u201c' (Safari) ## Error type `SyntaxError` ## What went wrong? There is an invalid character that the interpreter doesn't understand. You should either put it in a string literal or replace it with another character. Use an editor that supports syntax highlighting and carefully check your code against mismatches like a minus sign (`-`) versus a dash (`–`) or simple quotes (`"`) versus non-standard quotation marks (`“`). ## Examples ### Mismatched characters Some characters look similar, but will cause the parser to fail interpreting your code. Famous examples of this are quotes, the minus or semicolon (greek question mark (U+37e) looks same). “This looks like a string”; // SyntaxError: illegal character // “ and ” are not " but look like it 42 – 13; // SyntaxError: illegal character // – (en-dash) is not - but looks like it const foo = "bar"; // SyntaxError: illegal character // <37e> is not ; but looks like it This should work: "This is actually a string"; 42 - 13; const foo = "bar"; Some editors and IDEs will notify you or at least use a slightly different highlighting for it, but not all. When something like this happens to your code and you're not able to find the source of the problem, it's often best to just delete the problematic line and retype it. ### Forgotten characters It's easy to forget a character here or there. const operators = ["+", "-", ×", "÷"]; // SyntaxError: illegal character U+00D7 Add the missing quote for `"×"`. const operators = ["+", "-", "×", "÷"]; ### Hidden characters When copy pasting code from external sources, there might be invalid characters. Watch out! const foo = "bar";​ // SyntaxError: illegal character When inspecting this code in an editor like VIM, you can see that there is actually a zero-width space (ZWSP) (U+200B) character. const foo = "bar";<200b> ## See also * Lexical grammar # SyntaxError: import declarations may only appear at top level of a module The JavaScript exception "import declarations may only appear at top level of a module" occurs when an import declaration is not at the top level of a module. This might be because the import declaration is nested in other constructs (functions, blocks, etc.), or more often because the current file is not treated as a module. ## Message SyntaxError: Cannot use import statement outside a module (V8-based) SyntaxError: import declarations may only appear at top level of a module (Firefox) SyntaxError: Unexpected identifier 'x'. import call expects one or two arguments. (Safari) ## Error type `SyntaxError` ## What went wrong? You may have an `import` declaration that's nested in another construct, such as a function or a block. The `import` declaration must be at the top level of the module. If you want to conditionally import a module, or lazily import it on demand, use dynamic import instead. If the `import` is already at the top level of the code, it may be because the file is not interpreted as a module. Runtimes require external hints to determine whether a file is a module or not, and here are several ways to provide such hints: * If the file is directly loaded from HTML, make sure the ` If for some reason you cannot migrate the script to a module, you can use dynamic import. async function main() { const myModule = await import("./my-module.js"); // use myModule } main(); ## See also * Using modules * `import` * `import()` # TypeError: cannot use 'in' operator to search for 'x' in 'y' The JavaScript exception "right-hand side of 'in' should be an object" occurs when the `in` operator was used to search in strings, or in numbers, or other primitive types. It can only be used to check if a property is in an object. ## Message TypeError: Cannot use 'in' operator to search for 'x' in 'y' (V8-based & Firefox) TypeError: right-hand side of 'in' should be an object, got null (Firefox) TypeError: "y" is not an Object. (evaluating '"x" in "y"') (Safari) ## Error type `TypeError` ## What went wrong? The `in` operator can only be used to check if a property is in an object. You can't search in strings, or in numbers, or other primitive types. ## Examples ### Searching in strings Unlike in other programming languages (e.g., Python), you can't search in strings using the `in` operator. "Hello" in "Hello World"; // TypeError: cannot use 'in' operator to search for 'Hello' in 'Hello World' Instead you will need to use `String.prototype.includes()`, for example. "Hello World".includes("Hello"); // true ### The operand can't be null or undefined Make sure the object you are inspecting isn't actually `null` or `undefined`. const foo = null; "bar" in foo; // TypeError: cannot use 'in' operator to search for 'bar' in 'foo' (Chrome) // TypeError: right-hand side of 'in' should be an object, got null (Firefox) The `in` operator always expects an object. const foo = { baz: "bar" }; "bar" in foo; // false "PI" in Math; // true "pi" in Math; // false ### Searching in arrays Be careful when using the `in` operator to search in `Array` objects. The `in` operator checks the index number, not the value at that index. const trees = ["redwood", "bay", "cedar", "oak", "maple"]; 3 in trees; // true "oak" in trees; // false ## See also * `in` # RangeError: invalid array length The JavaScript exception "Invalid array length" occurs when specifying an array length that is either negative, a floating number or exceeds the maximum supported by the platform (i.e., when creating an `Array` or `ArrayBuffer`, or when setting the `length` property). The maximum allowed array length depends on the platform, browser and browser version. For `Array` the maximum length is 232-1. For `ArrayBuffer` the maximum is 231-1 (2GiB-1) on 32-bit systems. From Firefox version 89 the maximum value of `ArrayBuffer` is 233 (8GiB) on 64-bit systems. **Note:** `Array` and `ArrayBuffer` are independent data structures (the implementation of one does not affect the other). ## Message RangeError: invalid array length (V8-based & Firefox) RangeError: Array size is not a small enough positive integer. (Safari) RangeError: Invalid array buffer length (V8-based) RangeError: length too large (Safari) ## Error type `RangeError` ## What went wrong? The error might appear when attempting to produce an `Array` or `ArrayBuffer` with an invalid length, which includes: * Negative length, via the constructor or setting the `length` property. * Non-integer length, via the constructor or setting the `length` property. (The `ArrayBuffer` constructor coerces the length to an integer, but the `Array` constructor does not.) * Exceeding the maximum length supported by the platform. For arrays, the maximum length is 232-1. For `ArrayBuffer`, the maximum length is 231-1 (2GiB-1) on 32-bit systems, or 233 (8GiB) on 64-bit systems. This can happen via the constructor, setting the `length` property, or array methods that implicitly set the length property (such as `push` and `concat`). If you are creating an `Array` using the constructor, you probably want to use the literal notation instead, as the first argument is interpreted as the length of the `Array`. Otherwise, you might want to clamp the length before setting the length property, or using it as argument of the constructor. ## Examples ### Invalid cases new Array(2 ** 40); new Array(-1); new ArrayBuffer(2 ** 32); // 32-bit system new ArrayBuffer(-1); const a = []; a.length -= 1; // set the length property to -1 const b = new Array(2 ** 32 - 1); b.length += 1; // set the length property to 2^32 b.length = 2.5; // set the length property to a floating-point number const c = new Array(2.5); // pass a floating-point number // Concurrent modification that accidentally grows the array infinitely const arr = [1, 2, 3]; for (const e of arr) { arr.push(e * 10); } ### Valid cases [2 ** 40]; // [ 1099511627776 ] [-1]; // [ -1 ] new ArrayBuffer(2 ** 31 - 1); new ArrayBuffer(2 ** 33); // 64-bit systems after Firefox 89 new ArrayBuffer(0); const a = []; a.length = Math.max(0, a.length - 1); const b = new Array(2 ** 32 - 1); b.length = Math.min(0xffffffff, b.length + 1); // 0xffffffff is the hexadecimal notation for 2^32 - 1 // which can also be written as (-1 >>> 0) b.length = 3; const c = new Array(3); // Because array methods save the length before iterating, it is safe to grow // the array during iteration const arr = [1, 2, 3]; arr.forEach((e) => arr.push(e * 10)); ## See also * `Array` * `length` * `ArrayBuffer` # SyntaxError: invalid assignment left-hand side The JavaScript exception "invalid assignment left-hand side" occurs when there was an unexpected assignment somewhere. It may be triggered when a single `=` sign was used instead of `==` or `===`. ## Message SyntaxError: Invalid left-hand side in assignment (V8-based) SyntaxError: invalid assignment left-hand side (Firefox) SyntaxError: Left side of assignment is not a reference. (Safari) ReferenceError: Invalid left-hand side in assignment (V8-based) ReferenceError: cannot assign to function call (Firefox) ReferenceError: Left side of assignment is not a reference. (Safari) ## Error type `SyntaxError` or `ReferenceError`, depending on the syntax. ## What went wrong? There was an unexpected assignment somewhere. This might be due to a mismatch of an assignment operator and an equality operator, for example. While a single `=` sign assigns a value to a variable, the `==` or `===` operators compare a value. ## Examples ### Typical invalid assignments if (Math.PI + 1 = 3 || Math.PI + 1 = 4) { console.log("no way!"); } // SyntaxError: invalid assignment left-hand side const str = "Hello, " += "is it me " += "you're looking for?"; // SyntaxError: invalid assignment left-hand side In the `if` statement, you want to use an equality operator (`===`), and for the string concatenation, the plus (`+`) operator is needed. if (Math.PI + 1 === 3 || Math.PI + 1 === 4) { console.log("no way!"); } const str = "Hello, " + "from the " + "other side!"; ### Assignments producing ReferenceErrors Invalid assignments don't always produce syntax errors. Sometimes the syntax is almost correct, but at runtime, the left hand side expression evaluates to a _value_ instead of a _reference_ , so the assignment is still invalid. Such errors occur later in execution, when the statement is actually executed. function foo() { return { a: 1 }; } foo() = 1; // ReferenceError: invalid assignment left-hand side Function calls, `new` calls, `super()`, and `this` are all values instead of references. If you want to use them on the left hand side, the assignment target needs to be a property of their produced values instead. function foo() { return { a: 1 }; } foo().a = 1; **Note:** In Firefox and Safari, the first example produces a `ReferenceError` in non-strict mode, and a `SyntaxError` in strict mode. Chrome throws a runtime `ReferenceError` for both strict and non-strict modes. ### Using optional chaining as assignment target Optional chaining is not a valid target of assignment. obj?.foo = 1; // SyntaxError: invalid assignment left-hand side Instead, you have to first guard the nullish case. if (obj) { obj.foo = 1; } ## See also * Assignment operators * Equality operators # SyntaxError: invalid BigInt syntax The JavaScript exception "invalid BigInt syntax" occurs when a string value is being coerced to a `BigInt` but it failed to be parsed as an integer. ## Message SyntaxError: Cannot convert x to a BigInt (V8-based) SyntaxError: invalid BigInt syntax (Firefox) SyntaxError: Failed to parse String to BigInt (Safari) ## Error type `SyntaxError`. ## What went wrong? When using the `BigInt()` function to convert a string to a BigInt, the string will be parsed in the same way as source code, and the resulting value must be an integer value. ## Examples ### Invalid cases const a = BigInt("1.5"); const b = BigInt("1n"); const c = BigInt.asIntN(4, "8n"); // SyntaxError: invalid BigInt syntax ### Valid cases const a = BigInt("1"); const b = BigInt(" 1 "); const c = BigInt.asIntN(4, "8"); ## See also * `BigInt` # TypeError: invalid assignment to const "x" The JavaScript exception "invalid assignment to const" occurs when it was attempted to alter a constant value. JavaScript `const` declarations can't be re-assigned or redeclared. ## Message TypeError: Assignment to constant variable. (V8-based) TypeError: invalid assignment to const 'x' (Firefox) TypeError: Attempted to assign to readonly property. (Safari) ## Error type `TypeError` ## What went wrong? A constant is a value that cannot be altered by the program during normal execution. It cannot change through re-assignment, and it can't be redeclared. In JavaScript, constants are declared using the `const` keyword. ## Examples ### Invalid redeclaration Assigning a value to the same constant name in the same block-scope will throw. const COLUMNS = 80; // … COLUMNS = 120; // TypeError: invalid assignment to const `COLUMNS' ### Fixing the error There are multiple options to fix this error. Check what was intended to be achieved with the constant in question. #### Rename If you meant to declare another constant, pick another name and re-name. This constant name is already taken in this scope. const COLUMNS = 80; const WIDE_COLUMNS = 120; #### const, let or var? Do not use const if you weren't meaning to declare a constant. Maybe you meant to declare a block-scoped variable with `let` or global variable with `var`. let columns = 80; // … columns = 120; #### Scoping Check if you are in the correct scope. Should this constant appear in this scope or was it meant to appear in a function, for example? const COLUMNS = 80; function setupBigScreenEnvironment() { const COLUMNS = 120; } ### const and immutability The `const` declaration creates a read-only reference to a value. It does **not** mean the value it holds is immutable, just that the variable identifier cannot be reassigned. For instance, in case the content is an object, this means the object itself can still be altered. This means that you can't mutate the value stored in a variable: const obj = { foo: "bar" }; obj = { foo: "baz" }; // TypeError: invalid assignment to const `obj' But you can mutate the properties in a variable: obj.foo = "baz"; obj; // { foo: "baz" } ## See also * `const` * `let` * `var` # RangeError: invalid date The JavaScript exception "invalid date" occurs when an invalid date is attempted to be converted to an ISO date string. ## Message RangeError: Invalid time value (V8-based) RangeError: invalid date (Firefox) RangeError: Invalid Date (Safari) ## Error type `RangeError` ## What went wrong? You are converting an invalid date value to an ISO date string. This usually happens in one of three ways: * Calling the `toISOString()` method * Calling the `toJSON()` method, which implicitly calls `toISOString` * Using `JSON.stringify()` to stringify the date, which implicitly calls `toJSON` An _invalid date_ is produced when you attempt to parse an invalid date string, or set the timestamp to an out-of-bounds value. Invalid dates usually cause all date methods to return `NaN` or other special values. However, such dates do not have valid ISO string representations, so an error is thrown when you attempt to do so. ## Examples ### Invalid cases const invalid = new Date("nothing"); invalid.toISOString(); // RangeError: invalid date invalid.toJSON(); // RangeError: invalid date JSON.stringify({ date: invalid }); // RangeError: invalid date However, most other methods return special values: invalid.toString(); // "Invalid Date" invalid.getDate(); // NaN For more details, see the `Date.parse()` documentation. ### Valid cases new Date("05 October 2011 14:48 UTC").toISOString(); // "2011-10-05T14:48:00.000Z" new Date(1317826080).toISOString(); // "2011-10-05T14:48:00.000Z" ## See also * `Date` * `Date.prototype.parse()` * `Date.prototype.toISOString()` # TypeError: derived class constructor returned invalid value x The JavaScript exception "derived class constructor returned invalid value x" occurs when a derived class constructor returns a value that is not an object or `undefined`. ## Message TypeError: Derived constructors may only return object or undefined (V8-based) TypeError: derived class constructor returned invalid value 1 (Firefox) TypeError: Cannot return a non-object type in the constructor of a derived class. (Safari) ## Error type `TypeError` ## What went wrong? Typically, a constructor does not need to return anything—the value of `this` is automatically returned when the class is constructed. A constructor can also return an object, and this object will override `this` as the newly constructed instance. However, returning something that's neither an object nor `undefined` is usually a mistake, because that value is ignored. In base classes and function constructors (using the `function` syntax), returning such a value is silently ignored, while in derived classes, it throws an error. ## Examples ### Invalid cases class Base { constructor() {} } class Derived extends Base { constructor() { return 2; } } new Derived(); // TypeError: derived class constructor returned invalid value 2 ### Valid cases class Base { constructor() {} } class Derived extends Base { constructor() { return { x: 1 }; } } new Derived(); // { x: 1 } ## See also * Classes * `extends` * `new` # SyntaxError: for-in loop head declarations may not have initializers The JavaScript strict mode-only exception "for-in loop head declarations may not have initializers" occurs when the head of a for...in contains an initializer expression, such as `for (var i = 0 in obj)`. This is not allowed in for-in loops in strict mode. In addition, lexical declarations with initializers like `for (const i = 0 in obj)` are not allowed outside strict mode either. ## Message SyntaxError: for-in loop variable declaration may not have an initializer. (V8-based) SyntaxError: for-in loop head declarations may not have initializers (Firefox) SyntaxError: a lexical declaration in the head of a for-in loop can't have an initializer (Firefox) SyntaxError: Cannot assign to the loop variable inside a for-in loop header. (Safari) ## Error type `SyntaxError`. ## What went wrong? The head of a for...in loop contains an initializer expression. That is, a variable is declared and assigned a value `for (var i = 0 in obj)`. In non- strict mode, this head declaration is silently ignored and behaves like `for (var i in obj)`. In strict mode, however, a `SyntaxError` is thrown. In addition, lexical declarations with initializers like `for (const i = 0 in obj)` are not allowed outside strict mode either, and will always produce a `SyntaxError`. ## Examples This example throws a `SyntaxError`: const obj = { a: 1, b: 2, c: 3 }; for (const i = 0 in obj) { console.log(obj[i]); } // SyntaxError: for-in loop head declarations may not have initializers ### Valid for-in loop You can remove the initializer (`i = 0`) in the head of the for-in loop. const obj = { a: 1, b: 2, c: 3 }; for (const i in obj) { console.log(obj[i]); } ### Array iteration The for...in loop shouldn't be used for Array iteration. Did you intend to use a `for` loop instead of a `for-in` loop to iterate an `Array`? The `for` loop allows you to set an initializer then as well: const arr = ["a", "b", "c"]; for (let i = 2; i < arr.length; i++) { console.log(arr[i]); } // "c" ## See also * `for...in` * `for...of` * `for` # SyntaxError: a declaration in the head of a for-of loop can't have an initializer The JavaScript exception "a declaration in the head of a for-of loop can't have an initializer" occurs when the head of a for...of loop contains an initializer expression such as `for (const i = 0 of iterable)`. This is not allowed in for-of loops. ## Message SyntaxError: for-of loop variable declaration may not have an initializer. (V8-based) SyntaxError: a declaration in the head of a for-of loop can't have an initializer (Firefox) SyntaxError: Cannot assign to the loop variable inside a for-of loop header. (Safari) ## Error type `SyntaxError` ## What went wrong? The head of a for...of loop contains an initializer expression. That is, a variable is declared and assigned a value `for (const i = 0 of iterable)`. This is not allowed in for-of loops. You might want a `for` loop that does allow an initializer. ## Examples ### Invalid for-of loop const iterable = [10, 20, 30]; for (const value = 50 of iterable) { console.log(value); } // SyntaxError: a declaration in the head of a for-of loop can't // have an initializer ### Valid for-of loop You need to remove the initializer (`value = 50`) in the head of the `for-of` loop. Maybe you intended to make 50 an offset value, in that case you could add it to the loop body, for example. const iterable = [10, 20, 30]; for (let value of iterable) { value += 50; console.log(value); } // 60 // 70 // 80 ## See also * `for...of` * `for...in` * `for` # TypeError: invalid 'instanceof' operand 'x' The JavaScript exception "invalid 'instanceof' operand" occurs when the right- hand side operands of the `instanceof` operator isn't used with a constructor object, i.e., an object which has a `prototype` property and is callable. ## Message TypeError: Right-hand side of 'instanceof' is not an object (V8-based) TypeError: invalid 'instanceof' operand "x" (Firefox) TypeError: Right hand side of instanceof is not an object (Safari) TypeError: Right-hand side of 'instanceof' is not callable (V8-based) TypeError: x is not a function (Firefox) TypeError: x is not a function. (evaluating 'x instanceof y') (Safari) TypeError: Function has non-object prototype 'undefined' in instanceof check (V8-based) TypeError: 'prototype' property of x is not an object (Firefox) TypeError: instanceof called on an object with an invalid prototype property. (Safari) ## Error type `TypeError` ## What went wrong? The `instanceof` operator expects the right-hand-side operands to be a constructor object, i.e., an object which has a `prototype` property and is callable. It can also be an object with a `Symbol.hasInstance` method. This error can occur if: * The right-hand side operand is not an object. * The right-hand side operand is not a callable and it has no `Symbol.hasInstance` method. * The right-hand side operand is a callable, but its `prototype` property is not an object. (For example, arrow functions do not have a `prototype` property.) ## Examples ### instanceof vs. typeof "test" instanceof ""; // TypeError: invalid 'instanceof' operand "" 42 instanceof 0; // TypeError: invalid 'instanceof' operand 0 function Foo() {} const f = Foo(); // Foo() is called and returns undefined const x = new Foo(); x instanceof f; // TypeError: invalid 'instanceof' operand f x instanceof x; // TypeError: x is not a function To fix these errors, you will either need to replace the `instanceof` operator with the `typeof` operator, or to make sure you use the function name, instead of the result of its evaluation. typeof "test" === "string"; // true typeof 42 === "number"; // true function Foo() {} const f = Foo; // Do not call Foo. const x = new Foo(); x instanceof f; // true x instanceof Foo; // true ## See also * `instanceof` * `typeof` # TypeError: 'x' is not iterable The JavaScript exception "is not iterable" occurs when the value which is spread into an array or function call, given as the right-hand side of `for...of`, as argument of a function such as `Promise.all` or `Set()`, or as the right-hand side of an array destructuring, is not an iterable object. This error is also encountered when `Array.fromAsync()` or `for await...of` is used with a non-async iterable. ## Message TypeError: Spread syntax requires ...iterable[Symbol.iterator] to be a function (V8-based & Safari) TypeError: %Array%.from requires that the property of the first argument, items[Symbol.iterator], when exists, be a function (V8-based & Safari) TypeError: Array.fromAsync requires that the property of the first argument, items[Symbol.asyncIterator], when exists, be a function (V8-based & Safari) TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator)) (V8-based) TypeError: x is not async iterable (V8-based) TypeError: x is not iterable (V8-based & Firefox) TypeError: undefined is not a function (near '...y of x...') (Safari) TypeError: Array.from: no function (Safari) TypeError: Type error (Safari) ## Error type `TypeError` ## What went wrong? The value which is spread into an array or function call, given as the right- hand side of `for...of`, or as argument of a function such as `Promise.all` or `Set()`, or as the source of an array destructuring pattern, is not an iterable object. An iterable can be a built-in iterable type such as `Array`, `String` or `Map`, a generator result, or an object implementing the iterable protocol. const nonIterable1 = {}; const nonIterable2 = { [Symbol.iterator]: 1 }; [...nonIterable1]; Math.max(...nonIterable1); for (const x of nonIterable1); new Set(nonIterable1); Array.from(nonIterable2); new Int8Array(nonIterable2); const [] = nonIterable1; ## Examples ### Array destructuring a non-iterable const myObj = { arrayOrObjProp1: {}, arrayOrObjProp2: [42] }; const { arrayOrObjProp1: [value1], arrayOrObjProp2: [value2], } = myObj; // TypeError: object is not iterable console.log(value1, value2); The non-iterable might turn to be `undefined` in some runtime environments. ### Iterating over Object properties In JavaScript, `Object`s are not iterable unless they implement the iterable protocol. Therefore, you cannot use `for...of` to iterate over the properties of an object. const obj = { France: "Paris", England: "London" }; for (const p of obj) { // … } // TypeError: obj is not iterable Instead you have to use `Object.keys` or `Object.entries`, to iterate over the properties or entries of an object. const obj = { France: "Paris", England: "London" }; // Iterate over the property names: for (const country of Object.keys(obj)) { const capital = obj[country]; console.log(country, capital); } for (const [country, capital] of Object.entries(obj)) { console.log(country, capital); } Another option for this use case might be to use a `Map`: const map = new Map(); map.set("France", "Paris"); map.set("England", "London"); // Iterate over the property names: for (const country of map.keys()) { const capital = map.get(country); console.log(country, capital); } for (const capital of map.values()) { console.log(capital); } for (const [country, capital] of map.entries()) { console.log(country, capital); } ### Iterating over a generator Generator functions are functions you call to produce an iterable object. function* generate(a, b) { yield a; yield b; } for (const x of generate) { console.log(x); } // TypeError: generate is not iterable When they are not called, the `Function` object corresponding to the generator is callable, but not iterable. Calling a generator produces an iterable object which will iterate over the values yielded during the execution of the generator. function* generate(a, b) { yield a; yield b; } for (const x of generate(1, 2)) { console.log(x); } ### Iterating over a custom iterable Custom iterables can be created by implementing the `Symbol.iterator` method. You must be certain that your iterator method returns an object which is an iterator, which is to say it must have a next method. const myEmptyIterable = { [Symbol.iterator]() { return []; // [] is iterable, but it is not an iterator — it has no next method. }, }; Array.from(myEmptyIterable); // TypeError: myEmptyIterable is not iterable Here is a correct implementation: const myEmptyIterable = { [Symbol.iterator]() { return [][Symbol.iterator](); }, }; Array.from(myEmptyIterable); // [] ## See also * Iterable protocol * `Object.keys` * `Object.entries` * `Map` * Generator functions * for...of # SyntaxError: JSON.parse: bad parsing The JavaScript exceptions thrown by `JSON.parse()` occur when string failed to be parsed as JSON. ## Message SyntaxError: JSON.parse: unterminated string literal SyntaxError: JSON.parse: bad control character in string literal SyntaxError: JSON.parse: bad character in string literal SyntaxError: JSON.parse: bad Unicode escape SyntaxError: JSON.parse: bad escape character SyntaxError: JSON.parse: unterminated string SyntaxError: JSON.parse: no number after minus sign SyntaxError: JSON.parse: unexpected non-digit SyntaxError: JSON.parse: missing digits after decimal point SyntaxError: JSON.parse: unterminated fractional number SyntaxError: JSON.parse: missing digits after exponent indicator SyntaxError: JSON.parse: missing digits after exponent sign SyntaxError: JSON.parse: exponent part is missing a number SyntaxError: JSON.parse: unexpected end of data SyntaxError: JSON.parse: unexpected keyword SyntaxError: JSON.parse: unexpected character SyntaxError: JSON.parse: end of data while reading object contents SyntaxError: JSON.parse: expected property name or '}' SyntaxError: JSON.parse: end of data when ',' or ']' was expected SyntaxError: JSON.parse: expected ',' or ']' after array element SyntaxError: JSON.parse: end of data when property name was expected SyntaxError: JSON.parse: expected double-quoted property name SyntaxError: JSON.parse: end of data after property name when ':' was expected SyntaxError: JSON.parse: expected ':' after property name in object SyntaxError: JSON.parse: end of data after property value in object SyntaxError: JSON.parse: expected ',' or '}' after property value in object SyntaxError: JSON.parse: expected ',' or '}' after property-value pair in object literal SyntaxError: JSON.parse: property names must be double-quoted strings SyntaxError: JSON.parse: expected property name or '}' SyntaxError: JSON.parse: unexpected character SyntaxError: JSON.parse: unexpected non-whitespace character after JSON data ## Error type `SyntaxError` ## What went wrong? `JSON.parse()` parses a string as JSON. This string has to be valid JSON and will throw this error if incorrect syntax was encountered. ## Examples ### JSON.parse() does not allow trailing commas Both lines will throw a SyntaxError: JSON.parse("[1, 2, 3, 4,]"); JSON.parse('{"foo": 1,}'); // SyntaxError JSON.parse: unexpected character // at line 1 column 14 of the JSON data Omit the trailing commas to parse the JSON correctly: JSON.parse("[1, 2, 3, 4]"); JSON.parse('{"foo": 1}'); ### Property names must be double-quoted strings You cannot use single-quotes around properties, like 'foo'. JSON.parse("{'foo': 1}"); // SyntaxError: JSON.parse: expected property name or '}' // at line 1 column 2 of the JSON data Instead write "foo": JSON.parse('{"foo": 1}'); ### Leading zeros and decimal points You cannot use leading zeros, like 01, and decimal points must be followed by at least one digit. JSON.parse('{"foo": 01}'); // SyntaxError: JSON.parse: expected ',' or '}' after property value // in object at line 1 column 2 of the JSON data JSON.parse('{"foo": 1.}'); // SyntaxError: JSON.parse: unterminated fractional number // at line 1 column 2 of the JSON data Instead write just 1 without a zero and use at least one digit after a decimal point: JSON.parse('{"foo": 1}'); JSON.parse('{"foo": 1.0}'); ## See also * `JSON` * `JSON.parse()` * `JSON.stringify()` # TypeError: WeakSet key/WeakMap value 'x' must be an object or an unregistered symbol The JavaScript exception "WeakSet key (or WeakMap value) 'x' must be an object or an unregistered symbol" occurs when an value of invalid type is used as a key in a `WeakSet` or as a value in a `WeakMap`. ## Message TypeError: Invalid value used as weak map key (V8-based) TypeError: WeakMap key 1 must be an object or an unregistered symbol (Firefox) TypeError: WeakMap keys must be objects or non-registered symbols (Safari) TypeError: Invalid value used in weak set (V8-based) TypeError: WeakSet value 1 must be an object or an unregistered symbol (Firefox) TypeError: WeakSet values must be objects or non-registered symbols (Safari) ## Error type `TypeError` ## What went wrong? `WeakSet` and `WeakMap` require the keys to be _garbage collectable_. Only objects and non-registered symbols (that is, symbols not returned by `Symbol.for()`) are valid. For more information, see Memory management. If you want to add keys that are strings, numbers, or other primitive values, you should store them in a regular `Set` or `Map` instead. ## Examples ### Invalid cases new WeakSet().add(1); // TypeError new WeakMap().set(1, {}); // TypeError new WeakSet([1]); // TypeError new WeakMap([[1, {}]]); // TypeError ### Valid cases new WeakSet().add({}); // OK new WeakMap().set({}, 1); // OK new Set([1]); // OK new Map([[1, {}]]); // OK ## See also * Memory management * `WeakSet` * `WeakMap` * `Set` * `Map` # SyntaxError: label not found The JavaScript exception "label not found" occurs when a `break` or `continue` statement references a label that does not exist on any statement that contains the `break` or `continue` statement. ## Message SyntaxError: Undefined label 'label' (V8-based) SyntaxError: label not found (Firefox) SyntaxError: Cannot use the undeclared label 'label'. (Safari) ## Error type `SyntaxError`. ## What went wrong? In JavaScript, labels are very limited: you can only use them with `break` and `continue` statements, and you can only jump to them from a statement contained within the labeled statement. You cannot jump to this label from anywhere in the program. ## Examples ### Unsyntactic jump You cannot use labels as if they are `goto`. start: console.log("Hello, world!"); console.log("Do it again"); break start; Instead, you can only use labels to enhance the normal semantics of `break` and `continue` statements. start: { console.log("Hello, world!"); if (Math.random() > 0.5) { break start; } console.log("Maybe I'm logged"); } ## See also * Labeled statement # URIError: malformed URI sequence The JavaScript exception "malformed URI sequence" occurs when URI encoding or decoding wasn't successful. ## Message URIError: URI malformed (V8-based) URIError: malformed URI sequence (Firefox) URIError: String contained an illegal UTF-16 sequence. (Safari) ## Error type `URIError` ## What went wrong? URI encoding or decoding wasn't successful. An argument given to either the `decodeURI`, `encodeURI`, `encodeURIComponent`, or `decodeURIComponent` function was not valid, so that the function was unable encode or decode properly. ## Examples ### Encoding Encoding replaces each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character. An `URIError` will be thrown if there is an attempt to encode a surrogate which is not part of a high-low pair, for example: encodeURI("\uD800"); // "URIError: malformed URI sequence" encodeURI("\uDFFF"); // "URIError: malformed URI sequence" A high-low pair is OK. For example: encodeURI("\uD800\uDFFF"); // "%F0%90%8F%BF" ### Decoding Decoding replaces each escape sequence in the encoded URI component with the character that it represents. If there isn't such a character, an error will be thrown: decodeURIComponent("%E0%A4%A"); // "URIError: malformed URI sequence" With proper input, this should usually look like something like this: decodeURIComponent("JavaScript_%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"); // "JavaScript_шеллы" ## See also * `URIError` * `decodeURI` * `encodeURI` * `encodeURIComponent` * `decodeURIComponent` # SyntaxError: missing ] after element list The JavaScript exception "missing ] after element list" occurs when there is an error with the array initializer syntax somewhere. Likely there is a closing square bracket (`]`) or a comma (`,`) missing. ## Message SyntaxError: missing ] after element list (Firefox) SyntaxError: Unexpected token ';'. Expected either a closing ']' or a ',' following an array element. (Safari) ## Error type `SyntaxError`. ## What went wrong? There is an error with the array initializer syntax somewhere. Likely there is a closing square bracket (`]`) or a comma (`,`) missing. ## Examples ### Incomplete array initializer const list = [1, 2, const instruments = [ "Ukulele", "Guitar", "Piano", }; const data = [{ foo: "bar" } { bar: "foo" }]; Correct would be: const list = [1, 2]; const instruments = ["Ukulele", "Guitar", "Piano"]; const data = [{ foo: "bar" }, { bar: "foo" }]; ## See also * `Array` # SyntaxError: missing : after property id The JavaScript exception "missing : after property id" occurs when objects are created using the object initializer syntax. A colon (`:`) separates keys and values for the object's properties. Somehow, this colon is missing or misplaced. ## Message SyntaxError: Invalid shorthand property initializer (V8-based) SyntaxError: missing : after property id (Firefox) SyntaxError: Unexpected token '='. Expected a ':' following the property name 'x'. (Safari) SyntaxError: Unexpected token '+'. Expected an identifier as property name. (Safari) ## Error type `SyntaxError` ## What went wrong? When creating objects with the object initializer syntax, a colon (`:`) separates keys and values for the object's properties. const obj = { propertyKey: "value" }; ## Examples ### Colons vs. equal signs This code fails, as the equal sign can't be used this way in this object initializer syntax. const obj = { propertyKey = "value" }; // SyntaxError: missing : after property id Correct would be to use a colon, or to use square brackets to assign a new property after the object has been created already. const obj = { propertyKey: "value" }; Or alternatively: const obj = {}; obj.propertyKey = "value"; ### Computed properties If you create a property key from an expression, you need to use square brackets. Otherwise the property name can't be computed: const obj = { "b"+"ar": "foo" }; // SyntaxError: missing : after property id Put the expression in square brackets `[]`: const obj = { ["b" + "ar"]: "foo" }; ## See also * Object initializer # SyntaxError: missing } after function body The JavaScript exception "missing } after function body" occurs when there is a syntax mistake when creating a function somewhere. Check if any closing curly braces or parenthesis are in the correct order. ## Message SyntaxError: missing } after function body (Firefox) ## Error type `SyntaxError` ## What went wrong? There is a syntax mistake when creating a function somewhere. Also check if any closing curly braces or parenthesis are in the correct order. Indenting or formatting the code a bit nicer might also help you to see through the jungle. ## Examples ### Forgotten closing curly bracket Oftentimes, there is a missing curly bracket in your function code: function charge() { if (sunny) { useSolarCells(); } else { promptBikeRide(); } Correct would be: function charge() { if (sunny) { useSolarCells(); } else { promptBikeRide(); } } It can be more obscure when using IIFEs or other constructs that use a lot of different parenthesis and curly braces, for example. (function () { if (Math.random() < 0.01) { doSomething(); } )(); Oftentimes, indenting differently or double checking indentation helps to spot these errors. (function () { if (Math.random() < 0.01) { doSomething(); } })(); ## See also * Functions guide # SyntaxError: missing } after property list The JavaScript exception "missing } after property list" occurs when there is a mistake in the object initializer syntax somewhere. Might be in fact a missing curly bracket, but could also be a missing comma. ## Message SyntaxError: missing } after property list (Firefox) SyntaxError: Unexpected identifier 'c'. Expected '}' to end an object literal. (Safari) ## Error type `SyntaxError` ## What went wrong? There is a mistake in the object initializer syntax somewhere. Might be in fact a missing curly bracket, but could also be a missing comma, for example. Also check if any closing curly braces or parenthesis are in the correct order. Indenting or formatting the code a bit nicer might also help you to see through the jungle. ## Examples ### Forgotten comma Oftentimes, there is a missing comma in your object initializer code: const obj = { a: 1, b: { myProp: 2 } c: 3 }; Correct would be: const obj = { a: 1, b: { myProp: 2 }, c: 3, }; ## See also * Object initializer # SyntaxError: missing formal parameter The JavaScript exception "missing formal parameter" occurs when your function declaration is missing valid parameters. ## Message SyntaxError: missing formal parameter (Firefox) SyntaxError: Unexpected number '3'. Expected a parameter pattern or a ')' in parameter list. (Safari) SyntaxError: Unexpected string literal "x". Expected a parameter pattern or a ')' in parameter list. (Safari) ## Error type `SyntaxError` ## What went wrong? "Formal parameter" is a fancy way of saying "function parameter". Your function declaration is missing valid parameters. In the declaration of a function, the parameters must be identifiers, not any value like numbers, strings, or objects. Declaring functions and calling functions are two separate steps. Declarations require identifier as parameters, and only when calling (invoking) the function, you provide the values the function should use. In JavaScript, identifiers can contain only alphanumeric characters (or "$" or "_"), and may not start with a digit. An identifier differs from a **string** in that a string is data, while an identifier is part of the code. ## Examples ### Provide proper function parameters Function parameters must be identifiers when setting up a function. All these function declarations fail, as they are providing values for their parameters: function square(3) { return number * number; } // SyntaxError: missing formal parameter function greet("Howdy") { return greeting; } // SyntaxError: missing formal parameter function log({ obj: "value"}) { console.log(arg) } // SyntaxError: missing formal parameter You will need to use identifiers in function declarations: function square(number) { return number * number; } function greet(greeting) { return greeting; } function log(arg) { console.log(arg); } You can then call these functions with the arguments you like: square(2); // 4 greet("Howdy"); // "Howdy" log({ obj: "value" }); // { obj: "value" } ## See also * SyntaxError: redeclaration of formal parameter "x" # SyntaxError: missing = in const declaration The JavaScript exception "missing = in const declaration" occurs when a const declaration was not given a value in the same statement (like `const RED_FLAG;`). You need to provide one (`const RED_FLAG = "#ff0"`). ## Message SyntaxError: Missing initializer in const declaration (V8-based) SyntaxError: missing = in const declaration (Firefox) SyntaxError: Unexpected token ';'. const declared variable 'x' must have an initializer. (Safari) ## Error type `SyntaxError` ## What went wrong? A constant is a value that cannot be altered by the program during normal execution. It cannot change through re-assignment, and it can't be redeclared. In JavaScript, constants are declared using the `const` keyword. An initializer for a constant is required; that is, you must specify its value in the same statement in which it's declared (which makes sense, given that it can't be changed later). ## Examples ### Missing const initializer Unlike `var` or `let`, you must specify a value for a `const` declaration. This throws: const COLUMNS; // SyntaxError: missing = in const declaration ### Fixing the error There are multiple options to fix this error. Check what was intended to be achieved with the constant in question. #### Adding a constant value Specify the constant value in the same statement in which it's declared: const COLUMNS = 80; #### `const`, `let` or `var`? Do not use `const` if you weren't meaning to declare a constant. Maybe you meant to declare a block-scoped variable with `let` or global variable with `var`. Both don't require an initial value. let columns; ## See also * `const` * `let` * `var` # SyntaxError: missing name after . operator The JavaScript exception "missing name after . operator" occurs when there is a problem with how the dot operator (`.`) is used for property access. ## Message SyntaxError: missing name after . operator (Firefox) SyntaxError: Unexpected token '['. Expected a property name after '.'. (Safari) ## Error type `SyntaxError` ## What went wrong? The dot operator (`.`) is used for property access. You will have to specify the name of the property that you want to access. For computed property access, you might need to change your property access from using a dot to using square brackets. These will allow you to compute an expression. Maybe you intended to do concatenation instead? A plus operator (`+`) is needed in that case. Please see the examples below. ## Examples ### Property access Property accessors in JavaScript use either the dot (.) or square brackets (`[]`), but not both. Square brackets allow computed property access. const obj = { foo: { bar: "baz", bar2: "baz2" } }; const i = 2; obj.[foo].[bar] // SyntaxError: missing name after . operator obj.foo."bar"+i; // SyntaxError: missing name after . operator To fix this code, you need to access the object like this: obj.foo.bar; // "baz" // or alternatively obj["foo"]["bar"]; // "baz" // computed properties require square brackets obj.foo["bar" + i]; // "baz2" // or as template literal obj.foo[`bar${i}`]; // "baz2" ### Property access vs. concatenation If you are coming from another programming language (like PHP), it is also easy to mix up the dot operator (`.`) and the concatenation operator (`+`). console.log("Hello" . "world"); // SyntaxError: missing name after . operator Instead you need to use a plus sign for concatenation: console.log("Hello" + "World"); ## See also * Property accessors # SyntaxError: missing ) after argument list The JavaScript exception "missing ) after argument list" occurs when there is an error with how a function is called. This might be a typo, a missing operator, or an unescaped string. ## Message SyntaxError: missing ) after argument list (V8-based & Firefox) SyntaxError: Unexpected identifier 'x'. Expected ')' to end an argument list. (Safari) ## Error type `SyntaxError`. ## What went wrong? There is an error with how a function is called. This might be a typo, a missing operator, or an unescaped string, for example. ## Examples Because there is no "+" operator to concatenate the string, JavaScript expects the argument for the `log` function to be just `"PI: "`. In that case, it should be terminated by a closing parenthesis. console.log("PI: " Math.PI); // SyntaxError: missing ) after argument list You can correct the `log` call by adding the `+` operator: console.log("PI: " + Math.PI); // "PI: 3.141592653589793" Alternatively, you can consider using a template literal, or take advantage of the fact that `console.log` accepts multiple parameters: console.log(`PI: ${Math.PI}`); console.log("PI:", Math.PI); ### Unterminated strings console.log('"Java" + "Script" = \"' + "Java" + 'Script\"); // SyntaxError: missing ) after argument list Here JavaScript thinks that you meant to have `);` inside the string and ignores it, and it ends up not knowing that you meant the `);` to end the function `console.log`. To fix this, we could put a `'` after the "Script" string: console.log('"Java" + "Script" = "' + "Java" + 'Script"'); // '"Java" + "Script" = "JavaScript"' ## See also * Functions guide # SyntaxError: missing ) after condition The JavaScript exception "missing ) after condition" occurs when there is an error with how an `if` condition is written. It must appear in parenthesis after the `if` keyword. ## Message SyntaxError: missing ) after condition (Firefox) SyntaxError: Unexpected token '{'. Expected ')' to end an 'if' condition. (Safari) ## Error type `SyntaxError` ## What went wrong? There is an error with how an `if` condition is written. In any programming language, code needs to make decisions and carry out actions accordingly depending on different inputs. The if statement executes a statement if a specified condition is truthy. In JavaScript, this condition must appear in parenthesis after the `if` keyword, like this: if (condition) { // do something if the condition is true } ## Examples ### Missing parenthesis It might just be an oversight, carefully check all you parenthesis in your code. if (Math.PI < 3 { console.log("wait what?"); } // SyntaxError: missing ) after condition To fix this code, you would need to add a parenthesis that closes the condition. if (Math.PI < 3) { console.log("wait what?"); } ### Misused is keyword If you are coming from another programming language, it is also easy to add keywords that don't mean the same or have no meaning at all in JavaScript. if (done is true) { console.log("we are done!"); } // SyntaxError: missing ) after condition Instead you need to use a correct comparison operator. For example: if (done === true) { console.log("we are done!"); } Or even better: if (done) { console.log("we are done!"); } ## See also * `if...else` * Relational operators * Learn: Making decisions in your code — conditionals # TypeError: More arguments needed The JavaScript exception "more arguments needed" occurs when there is an error with how a function is called. More arguments need to be provided. ## Message TypeError: Object prototype may only be an Object or null: undefined (V8-based) TypeError: Object.create requires at least 1 argument, but only 0 were passed (Firefox) TypeError: Object.setPrototypeOf requires at least 2 arguments, but only 0 were passed (Firefox) TypeError: Object.defineProperties requires at least 1 argument, but only 0 were passed (Firefox) TypeError: Object prototype may only be an Object or null. (Safari) ## Error type `TypeError`. ## What went wrong? There is an error with how a function is called. More arguments need to be provided. ## Examples ### Required arguments not provided The `Object.create()` method requires at least one argument and the `Object.setPrototypeOf()` method requires at least two arguments: const obj = Object.create(); // TypeError: Object.create requires at least 1 argument, but only 0 were passed const obj2 = Object.setPrototypeOf({}); // TypeError: Object.setPrototypeOf requires at least 2 arguments, but only 1 were passed You can fix this by setting `null` as the prototype, for example: const obj = Object.create(null); const obj2 = Object.setPrototypeOf({}, null); ## See also * Functions guide # RangeError: repeat count must be non-negative The JavaScript exception "repeat count must be non-negative" occurs when the `String.prototype.repeat()` method is used with a `count` argument that is a negative number. ## Message RangeError: Invalid count value: -1 (V8-based) RangeError: repeat count must be non-negative (Firefox) RangeError: String.prototype.repeat argument must be greater than or equal to 0 and not be Infinity (Safari) ## Error type `RangeError` ## What went wrong? The `String.prototype.repeat()` method has been used. It has a `count` parameter indicating the number of times to repeat the string. It must be between 0 and less than positive `Infinity` and cannot be a negative number. The range of allowed values can be described like this: [0, +∞). ## Examples ### Invalid cases "abc".repeat(-1); // RangeError ### Valid cases "abc".repeat(0); // '' "abc".repeat(1); // 'abc' "abc".repeat(2); // 'abcabc' "abc".repeat(3.5); // 'abcabcabc' (count will be converted to integer) ## See also * `String.prototype.repeat()` # TypeError: "x" is not a non-null object The JavaScript exception "is not a non-null object" occurs when an object is expected somewhere and wasn't provided. `null` is not an object and won't work. ## Message TypeError: Property description must be an object: x (V8-based) TypeError: Property descriptor must be an object, got "x" (Firefox) TypeError: Property description must be an object. (Safari) ## Error type `TypeError` ## What went wrong? An object is expected somewhere and wasn't provided. `null` is not an object and won't work. You must provide a proper object in the given situation. ## Examples ### Property descriptor expected When methods like `Object.create()` or `Object.defineProperty()` and `Object.defineProperties()` are used, the optional descriptor parameter expects a property descriptor object. Providing no object (like just a number), will throw an error: Object.defineProperty({}, "key", 1); // TypeError: 1 is not a non-null object Object.defineProperty({}, "key", null); // TypeError: null is not a non-null object A valid property descriptor object might look like this: Object.defineProperty({}, "key", { value: "foo", writable: false }); ## See also * `Object.create()` * `Object.defineProperty()` * `Object.defineProperties()` # TypeError: null/undefined has no properties The JavaScript exception "null (or undefined) has no properties" occurs when you attempt to access properties of `null` and `undefined`. They don't have any. ## Message TypeError: Cannot read properties of undefined (reading 'x') (V8-based) TypeError: Cannot destructure 'x' as it is undefined. (V8-based) TypeError: Cannot destructure property 'x' of 'y' as it is undefined. (V8-based) TypeError: null has no properties (Firefox) TypeError: undefined has no properties (Firefox) TypeError: undefined is not an object (evaluating 'undefined.x') (Safari) TypeError: Right side of assignment cannot be destructured (Safari) ## Error type `TypeError`. ## What went wrong? Both `null` and `undefined` have no properties you could access. Therefore, you cannot use property accessors on them, or destructure them. ## Examples ### null and undefined have no properties null.foo; // TypeError: null has no properties undefined.bar; // TypeError: undefined has no properties ## See also * `null` * `undefined` # SyntaxError: missing variable name The JavaScript exception "missing variable name" is a common error. It is usually caused by omitting a variable name or a typographic error. ## Message SyntaxError: missing variable name (Firefox) SyntaxError: Unexpected token '='. Expected a parameter pattern or a ')' in parameter list. (Safari) ## Error type `SyntaxError` ## What went wrong? A variable is missing a name. The cause is most likely a typo or a forgotten variable name. Make sure that you've provided the name of the variable before the `=` sign. When declaring multiple variables at the same time, make sure that the previous lines/declaration does not end with a comma instead of a semicolon. ## Examples ### Missing a variable name const = "foo"; It is easy to forget to assign a name for your variable! const description = "foo"; ### Reserved keywords can't be variable names There are a few variable names that are reserved keywords. You can't use these. Sorry :( const debugger = "whoop"; // SyntaxError: missing variable name ### Declaring multiple variables Pay special attention to commas when declaring multiple variables. Is there an excess comma, or did you use commas instead of semicolons? Did you remember to assign values for all your `const` variables? let x, y = "foo", const z, = "foo" const first = document.getElementById("one"), const second = document.getElementById("two"), // SyntaxError: missing variable name The fixed version: let x, y = "foo"; const z = "foo"; const first = document.getElementById("one"); const second = document.getElementById("two"); ### Arrays `Array` literals in JavaScript need square brackets around the values. This won't work: const arr = 1,2,3,4,5; // SyntaxError: missing variable name This would be correct: const arr = [1, 2, 3, 4, 5]; ## See also * Lexical grammar * `var` * Grammar and types guide # TypeError: can't delete non-configurable array element The JavaScript exception "can't delete non-configurable array element" occurs when it was attempted to shorten the length of an array, but one of the array's elements is non-configurable. ## Message TypeError: Cannot delete property '1' of [object Array] (V8-based) TypeError: can't delete non-configurable array element (Firefox) TypeError: Unable to delete property. (Safari) ## Error type `TypeError` ## What went wrong? It was attempted to shorten the length of an array, but one of the array's elements is non-configurable. When shortening an array, the elements beyond the new array length will be deleted, which failed in this situation. The `configurable` attribute controls whether the property can be deleted from the object and whether its attributes (other than `writable`) can be changed. Usually, properties in an object created by an array initializer are configurable. However, for example, when using `Object.defineProperty()`, the property isn't configurable by default. ## Examples ### Non-configurable properties created by Object.defineProperty The `Object.defineProperty()` creates non-configurable properties by default if you haven't specified them as configurable. "use strict"; const arr = []; Object.defineProperty(arr, 0, { value: 0 }); Object.defineProperty(arr, 1, { value: "1" }); arr.length = 1; // TypeError: can't delete non-configurable array element You will need to set the elements as configurable, if you intend to shorten the array. "use strict"; const arr = []; Object.defineProperty(arr, 0, { value: 0, configurable: true }); Object.defineProperty(arr, 1, { value: "1", configurable: true }); arr.length = 1; ### Sealed Arrays The `Object.seal()` function marks all existing elements as non-configurable. "use strict"; const arr = [1, 2, 3]; Object.seal(arr); arr.length = 1; // TypeError: can't delete non-configurable array element You either need to remove the `Object.seal()` call, or make a copy of it. In case of a copy, shortening the copy of the array does not modify the original array length. "use strict"; const arr = [1, 2, 3]; Object.seal(arr); // Copy the initial array to shorten the copy const copy = Array.from(arr); copy.length = 1; // arr.length === 3 ## See also * [[Configurable]] * `length` * `Object.defineProperty()` * `Object.seal()` # TypeError: "x" is not a constructor The JavaScript exception "is not a constructor" occurs when there was an attempt to use an object or a variable as a constructor, but that object or variable is not a constructor. ## Message TypeError: x is not a constructor (V8-based & Firefox & Safari) ## Error type `TypeError` ## What went wrong? There was an attempt to use an object or a variable as a constructor, but that object or variable is not a constructor. See constructor or the `new` operator for more information on what a constructor is. There are many global objects, like `String` or `Array`, which are constructable using `new`. However, some global objects are not and their properties and methods are static. The following JavaScript standard built-in objects are not a constructor: `Math`, `JSON`, `Symbol`, `Reflect`, `Intl`, `Atomics`. Generator functions cannot be used as constructors either. ## Examples ### Invalid cases const Car = 1; new Car(); // TypeError: Car is not a constructor new Math(); // TypeError: Math is not a constructor new Symbol(); // TypeError: Symbol is not a constructor function* f() {} const obj = new f(); // TypeError: f is not a constructor ### A car constructor Suppose you want to create an object type for cars. You want this type of object to be called `Car`, and you want it to have properties for make, model, and year. To do this, you would write the following function: function Car(make, model, year) { this.make = make; this.model = model; this.year = year; } Now you can create an object called `myCar` as follows: const myCar = new Car("Eagle", "Talon TSi", 1993); ### In Promises When returning an immediately-resolved or immediately-rejected Promise, you do not need to create a `new Promise(...)` and act on it. Instead, use the `Promise.resolve()` or `Promise.reject()` static methods. This is not legal (the `Promise` constructor is not being called correctly) and will throw a `TypeError: this is not a constructor` exception: function fn() { return new Promise.resolve(true); } This is legal, but unnecessarily long: function fn() { return new Promise((resolve, reject) => { resolve(true); }); } Instead, return the static method: function resolveAlways() { return Promise.resolve(true); } function rejectAlways() { return Promise.reject(new Error()); } ## See also * constructor * `new` # TypeError: "x" is not a function The JavaScript exception "is not a function" occurs when there was an attempt to call a value from a function, but the value is not actually a function. ## Message TypeError: "x" is not a function. (V8-based & Firefox & Safari) ## Error type `TypeError` ## What went wrong? It attempted to call a value from a function, but the value is not actually a function. Some code expects you to provide a function, but that didn't happen. Maybe there is a typo in the function name? Maybe the object you are calling the method on does not have this function? For example, JavaScript `Objects` have no `map` function, but the JavaScript `Array` object does. There are many built-in functions in need of a (callback) function. You will have to provide a function in order to have these methods working properly: * When working with `Array` or `TypedArray` objects: * `Array.prototype.every()`, `Array.prototype.some()`, `Array.prototype.forEach()`, `Array.prototype.map()`, `Array.prototype.filter()`, `Array.prototype.reduce()`, `Array.prototype.reduceRight()`, `Array.prototype.find()` * When working with `Map` and `Set` objects: * `Map.prototype.forEach()` and `Set.prototype.forEach()` ## Examples ### A typo in the function name In this case, which happens way too often, there is a typo in the method name: const x = document.getElementByID("foo"); // TypeError: document.getElementByID is not a function The correct function name is `getElementById`: const x = document.getElementById("foo"); ### Function called on the wrong object For certain methods, you have to provide a (callback) function and it will work on specific objects only. In this example, `Array.prototype.map()` is used, which will work with `Array` objects only. const obj = { a: 13, b: 37, c: 42 }; obj.map((num) => num * 2); // TypeError: obj.map is not a function Use an array instead: const numbers = [1, 4, 9]; numbers.map((num) => num * 2); // [2, 8, 18] ### Function shares a name with a pre-existing property Sometimes when making a class, you may have a property and a function with the same name. Upon calling the function, the compiler thinks that the function ceases to exist. function Dog() { this.age = 11; this.color = "black"; this.name = "Ralph"; return this; } Dog.prototype.name = function (name) { this.name = name; return this; }; const myNewDog = new Dog(); myNewDog.name("Cassidy"); // TypeError: myNewDog.name is not a function Use a different property name instead: function Dog() { this.age = 11; this.color = "black"; this.dogName = "Ralph"; // Using this.dogName instead of .name return this; } Dog.prototype.name = function (name) { this.dogName = name; return this; }; const myNewDog = new Dog(); myNewDog.name("Cassidy"); // Dog { age: 11, color: 'black', dogName: 'Cassidy' } ### Using parentheses for multiplication In math, you can write 2 × (3 + 5) as 2*(3 + 5) or just 2(3 + 5). Using the latter will throw an error: const sixteen = 2(3 + 5); console.log(`2 x (3 + 5) is ${sixteen}`); // Uncaught TypeError: 2 is not a function You can correct the code by adding a `*` operator: const sixteen = 2 * (3 + 5); console.log(`2 x (3 + 5) is ${sixteen}`); // 2 x (3 + 5) is 16 ### Import the exported module correctly Ensure you are importing the module correctly. An example helpers library (`helpers.js`) function helpers() {} helpers.groupBy = function (objectArray, property) { return objectArray.reduce((acc, obj) => { const key = obj[property]; acc[key] ??= []; acc[key].push(obj); return acc; }, {}); }; export default helpers; The correct import usage (`App.js`): import helpers from "./helpers"; ## See also * Functions # RangeError: argument is not a valid code point The JavaScript exception "Invalid code point" occurs when `NaN` values, negative Integers (-1), non-Integers (5.4), or values larger than 0x10FFFF (1114111) are used with `String.fromCodePoint()`. ## Message RangeError: Invalid code point -1 (V8-based) RangeError: -1 is not a valid code point (Firefox) RangeError: Arguments contain a value that is out of range of code points (Safari) ## Error type `RangeError` ## What went wrong? `String.fromCodePoint()` throws this error when passed `NaN` values, negative Integers (-1), non-Integers (5.4), or values larger than 0x10FFFF (1114111). A code point is a value in the Unicode codespace; that is, the range of integers from `0` to `0x10FFFF`. ## Examples ### Invalid cases String.fromCodePoint("_"); // RangeError String.fromCodePoint(Infinity); // RangeError String.fromCodePoint(-1); // RangeError String.fromCodePoint(3.14); // RangeError String.fromCodePoint(3e-2); // RangeError String.fromCodePoint(NaN); // RangeError ### Valid cases String.fromCodePoint(42); // "*" String.fromCodePoint(65, 90); // "AZ" String.fromCodePoint(0x404); // 'Є' (U+0404) String.fromCodePoint(0x2f804); // '你' (U+2F804) String.fromCodePoint(194564); // '你' String.fromCodePoint(0x1d306, 0x61, 0x1d307); // '𝌆a𝌇' ## See also * `String.fromCodePoint()` # ReferenceError: "x" is not defined The JavaScript exception "_variable_ is not defined" occurs when there is a non-existent variable referenced somewhere. ## Message ReferenceError: "x" is not defined (V8-based & Firefox) ReferenceError: Can't find variable: x (Safari) ## Error type `ReferenceError`. ## What went wrong? There is a non-existent variable referenced somewhere. This variable needs to be declared, or you need to make sure it is available in your current script or scope. **Note:** When loading a library (such as jQuery), make sure it is loaded before you access library variables, such as "$". Put the ` ## See also * ` The same concept applies to promises. If we modify the above example a little bit, we get this: If we change this so that the ` In the above example, the inner text of the `