Skip to content

Instantly share code, notes, and snippets.

@bgoonz
Created January 6, 2022 10:22
Show Gist options
  • Save bgoonz/ba23faf5e92cd0ff8bad2e65805987fc to your computer and use it in GitHub Desktop.
Save bgoonz/ba23faf5e92cd0ff8bad2e65805987fc to your computer and use it in GitHub Desktop.

var

The var declares a function-scoped or globally-scoped variable, optionally initializing it to a value.

Syntax

var varname1 [= value1] [, varname2 [= value2] ... [, varnameN [= valueN]]];

varnameN
Variable name. It can be any legal identifier.

valueN Optional
Initial value of the variable. It can be any legal expression. Default value is undefined.

Alternatively, the Destructuring Assignment syntax can also be used to declare variables.

var { bar } = foo; // where foo = { bar:10, baz:12 };
/* This creates a variable with the name 'bar', which has a value of 10 */

Description

var declarations, wherever they occur, are processed before any code is executed. This is called hoisting, and is discussed further below.

The scope of a variable declared with var is its current execution context and closures thereof, which is either the enclosing function and functions declared within it, or, for variables declared outside any function, global. Duplicate variable declarations using var will not trigger an error, even in strict mode, and the variable will not lose its value, unless another assignment is performed.

'use strict';
function foo() {
  var x = 1;
  function bar() {
    var y = 2;
    console.log(x); // 1 (function `bar` closes over `x`)
    console.log(y); // 2 (`y` is in scope)
  }
  bar();
  console.log(x); // 1 (`x` is in scope)
  console.log(y); // ReferenceError in strict mode, `y` is scoped to `bar`
}

foo();

Variables declared using var are created before any code is executed in a process known as hoisting. Their initial value is undefined.

'use strict';
console.log(x);                // undefined (note: not ReferenceError)
console.log('still going...'); // still going...
var x = 1;
console.log(x);                // 1
console.log('still going...'); // still going...

In the global context, a variable declared using var is added as a non-configurable property of the global object. This means its property descriptor cannot be changed and it cannot be deleted using delete. The corresponding name is also added to a list on the internal [[VarNames]] slot on the global environment record (which forms part of the global lexical environment). The list of names in [[VarNames]] enables the runtime to distinguish between global variables and straightforward properties on the global object.

The property created on the global object for global variables, is set to be non-configurable because the identifier is to be treated as a variable, rather than a straightforward property of the global object. JavaScript has automatic memory management, and it would make no sense to be able to use the delete operator on a global variable.

'use strict';
var x = 1;
globalThis.hasOwnProperty('x'); // true
delete globalThis.x; // TypeError in strict mode. Fails silently otherwise.
delete x;  // SyntaxError in strict mode. Fails silently otherwise.

Note that in both NodeJS CommonJS modules and native ECMAScript modules, top-level variable declarations are scoped to the module, and are not, therefore added as properties to the global object.

Unqualified identifier assignments

The global object sits at the top of the scope chain. When attempting to resolve a name to a value, the scope chain is searched. This means that properties on the global object are conveniently visible from every scope, without having to qualify the names with globalThis. or window. or global..

So you can just type:

function foo() {
  String('s') // Note the function `String` is implicitly visible
}

...because

globalThis.hasOwnProperty('String') // true

So the global object will ultimately be searched for unqualified identifiers. You don't have to type globalThis.String, you can just type the unqualified String. The corollary, in non-strict mode, is that assignment to unqualified identifiers will, if there is no variable of the same name declared in the scope chain, assume you want to create a property with that name on the global object.

foo = 'f' // In non-strict mode, assumes you want to create a property named `foo` on the global object
globalThis.hasOwnProperty('foo') // true

In ECMAScript 5, this behavior was changed for strict mode. Assignment to an unqualified identifier in strict mode will result in a ReferenceError, to avoid the accidental creation of properties on the global object.

Note that the implication of the above, is that, contrary to popular misinformation, JavaScript does not have implicit or undeclared variables, it merely has a syntax that looks like it does.

var hoisting

Because variable declarations (and declarations in general) are processed before any code is executed, declaring a variable anywhere in the code is equivalent to declaring it at the top. This also means that a variable can appear to be used before it's declared. This behavior is called "hoisting", as it appears that the variable declaration is moved to the top of the function or global code.

bla = 2;
var bla;

// ...is implicitly understood as:

var bla;
bla = 2;

For that reason, it is recommended to always declare variables at the top of their scope (the top of global code and the top of function code) so it's clear which variables are function scoped (local) and which are resolved on the scope chain.

It's important to point out that the hoisting will affect the variable declaration, but not its value's initialization. The value will be indeed assigned when the assignment statement is reached:

function do_something() {
  console.log(bar); // undefined
  var bar = 111;
  console.log(bar); // 111
}

// ...is implicitly understood as:

function do_something() {
  var bar;
  console.log(bar); // undefined
  bar = 111;
  console.log(bar); // 111
}

Examples

Declaring and initializing two variables

var a = 0, b = 0;

Assigning two variables with single string value

var a = 'A';
var b = a;

// ...is equivalent to:

var a, b = a = 'A';

Be mindful of the order:

var x = y, y = 'A';
console.log(x + y); // undefinedA

Here, x and y are declared before any code is executed, but the assignments occur later. At the time "x = y" is evaluated, y exists so no ReferenceError is thrown and its value is undefined. So, x is assigned the undefined value. Then, y is assigned the value 'A'. Consequently, after the first line, x === undefined && y === 'A', hence the result.

Initialization of several variables

var x = 0;
function f() {
  var x = y = 1; // Declares x locally; declares y globally.
}
f();

console.log(x, y); // 0 1

// In non-strict mode:
// x is the global one as expected;
// y is leaked outside of the function, though!

The same example as above but with a strict mode:

'use strict';

var x = 0;
function f() {
  var x = y = 1; // Throws a ReferenceError in strict mode.
}
f();

console.log(x, y);

Implicit globals and outer function scope

Variables that appear to be implicit globals may be references to variables in an outer function scope:

var x = 0; // Declares x within file scope, then assigns it a value of 0.

console.log(typeof z); // "undefined", since z doesn't exist yet

function a() {
  var y = 2; // Declares y within scope of function a, then assigns it a value of 2.

  console.log(x, y); // 0 2

  function b() {
    x = 3; // Assigns 3 to existing file scoped x.
    y = 4; // Assigns 4 to existing outer y.
    z = 5; // Creates a new global variable z, and assigns it a value of 5.
           // (Throws a ReferenceError in strict mode.)
  }

  b(); // Creates z as a global variable.
  console.log(x, y, z); // 3 4 5
}

a(); // Also calls b.
console.log(x, z);     // 3 5
console.log(typeof y); // "undefined", as y is local to function a

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-variable-statement

Browser compatibility

Desktop

Mobile

Chrome

Edge

Firefox

Internet Explorer

Opera

Safari

WebView Android

Chrome Android

Firefox for Android

Opera Android

Safari on IOS

Samsung Internet

var

1

12

1

3

3

1

1

18

4

10.1

1

1.0

See also

© 2005–2021 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var

TypeError: variable "x" redeclares argument

The JavaScript strict mode-only exception "variable redeclares argument" occurs when the same variable name occurs as a function parameter and is then redeclared using a var assignment in a function body again.

Message

TypeError: variable "x" redeclares argument (Firefox)

Error type

TypeError warning in strict mode only.

What went wrong?

The same variable name occurs as a function parameter and is then redeclared using a var assignment in a function body again. This might be a naming conflict and thus JavaScript warns about it.

This error occurs as a warning in strict mode code only. In non-strict code, the redeclaration is silently ignored.

Examples

Invalid cases

In this case, the variable "arg" redeclares the argument.

'use strict';

function f(arg) {
  var arg = 'foo';
}

Valid cases

To fix this warning, the var statement can just be omitted, because the variable exists already. In other cases, you might to rename either the function parameter or the variable name.

'use strict';

function f(arg) {
  arg = 'foo';
}

See also

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Var_hides_argument

void operator

The void evaluates the given expression and then returns undefined.

Syntax

void expression

Description

This operator allows evaluating expressions that produce a value into places where an expression that evaluates to undefined is desired.

The void operator is often used merely to obtain the undefined primitive value, usually using "void(0)" (which is equivalent to "void 0"). In these cases, the global variable undefined can be used.

It should be noted that the precedence of the void operator should be taken into account and that parentheses can help clarify the resolution of the expression following the void operator:

void 2 == '2';   // (void 2) == '2', returns false
void (2 == '2'); // void (2 == '2'), returns undefined

Examples

Immediately Invoked Function Expressions

When using an immediately-invoked function expression, void can be used to force the function keyword to be treated as an expression instead of a declaration.

void function iife() {

  console.log("Executed!");

}();

// Output: "Executed!"

Executing the above function without the void keyword will result in an Uncaught SyntaxError.

JavaScript URIs

When a browser follows a javascript: URI, it evaluates the code in the URI and then replaces the contents of the page with the returned value, unless the returned value is undefined. The void operator can be used to return undefined. For example:

<a href="javascript:void(0);">
  Click here to do nothing
</a>

<a href="javascript:void(document.body.style.backgroundColor='green');">
  Click here for green background
</a>

Note: javascript: pseudo protocol is discouraged over other alternatives, such as unobtrusive event handlers.

Non-leaking Arrow Functions

Arrow functions introduce a short-hand braceless syntax that returns an expression. This can cause unintended side effects by returning the result of a function call that previously returned nothing. To be safe, when the return value of a function is not intended to be used, it can be passed to the void operator to ensure that (for example) changing APIs do not cause arrow functions' behaviors to change.

button.onclick = () => void doSomething();

This ensures the return value of doSomething changing from undefined to true will not change the behavior of this code.

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-void-operator

Browser compatibility

Desktop

Mobile

Chrome

Edge

Firefox

Internet Explorer

Opera

Safari

WebView Android

Chrome Android

Firefox for Android

Opera Android

Safari on IOS

Samsung Internet

void

1

12

1

5

4

3.2

1

18

4

10.1

3

1.0

See also

© 2005–2021 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void

Atomics.wait()

The static Atomics``.wait() method verifies that a given position in an Int32Array still contains a given value and if so sleeps, awaiting a wakeup or a timeout. It returns a string which is either "ok", "not-equal", or "timed-out".

Note: This operation only works with a shared Int32Array and may not be allowed on the main thread.

Syntax

Atomics.wait(typedArray, index, value)
Atomics.wait(typedArray, index, value, timeout)

Parameters

typedArray
A shared Int32Array.

index
The position in the typedArray to wait on.

value
The expected value to test.

timeout Optional
Time to wait in milliseconds. Infinity, if no time is provided.

Return value

A string which is either "ok", "not-equal", or "timed-out".

Exceptions

Examples

Using wait()

Given a shared Int32Array:

const sab = new SharedArrayBuffer(1024);
const int32 = new Int32Array(sab);

A reading thread is sleeping and waiting on location 0 which is expected to be 0. As long as that is true, it will not go on. However, once the writing thread has stored a new value, it will be notified by the writing thread and return the new value (123).

Atomics.wait(int32, 0, 0);
console.log(int32[0]); // 123

A writing thread stores a new value and notifies the waiting thread once it has written:

console.log(int32[0]); // 0;
Atomics.store(int32, 0, 123);
Atomics.notify(int32, 0, 1);

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-atomics.wait

Browser compatibility

Desktop

Mobile

Chrome

Edge

Firefox

Internet Explorer

Opera

Safari

WebView Android

Chrome Android

Firefox for Android

Opera Android

Safari on IOS

Samsung Internet

wait

68

60-63

Chrome disabled SharedArrayBuffer on January 5, 2018 to help reduce the efficacy of speculative side-channel attacks. This was a temporary removal while mitigations were put in place.

79

16-17

Support was removed to mitigate speculative execution side-channel attacks (Windows blog).

78

57

Support was disabled by default to mitigate speculative execution side-channel attacks (Mozilla Security Blog).

55-57

48-55

46-48

The method returns values Atomics.OK, Atomics.TIMEDOUT, and Atomics.NOTEQUAL, instead of the later-specified strings.

No

No

10.1-11.1

60-63

Chrome disabled SharedArrayBuffer on January 5, 2018 to help reduce the efficacy of speculative side-channel attacks. This is intended as a temporary measure until other mitigations are in place.

60-63

Chrome disabled SharedArrayBuffer on January 5, 2018 to help reduce the efficacy of speculative side-channel attacks. This is intended as a temporary measure until other mitigations are in place.

57

Support was disabled by default to mitigate speculative execution side-channel attacks (Mozilla Security Blog).

55-57

48-55

46-48

The method returns values Atomics.OK, Atomics.TIMEDOUT, and Atomics.NOTEQUAL, instead of the later-specified strings.

No

10.3-11.3

No

Chrome disabled SharedArrayBuffer on January 5, 2018 to help reduce the efficacy of speculative side-channel attacks. This is intended as a temporary measure until other mitigations are in place.

See also

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/wait

WeakMap

The WeakMap object is a collection of key/value pairs in which the keys are weakly referenced. The keys must be objects and the values can be arbitrary values.

You can learn more about WeakMaps in the WeakMap object guide (under Keyed collections).

Description

Keys of WeakMaps are of the type Object only. Primitive data types as keys are not allowed (e.g. a Symbol can't be a WeakMap key).

Why WeakMap?

A map API could be implemented in JavaScript with two arrays (one for keys, one for values) shared by the four API methods. Setting elements on this map would involve pushing a key and value onto the end of each of those arrays simultaneously. As a result, the indices of the key and value would correspond to both arrays. Getting values from the map would involve iterating through all keys to find a match, then using the index of this match to retrieve the corresponding value from the array of values.

Such an implementation would have two main inconveniences:

  1. The first one is an O(n) set and search (n being the number of keys in the map) since both operations must iterate through the list of keys to find a matching value.
  2. The second inconvenience is a memory leak because the arrays ensure that references to each key and each value are maintained indefinitely. These references prevent the keys from being garbage collected, even if there are no other references to the object. This would also prevent the corresponding values from being garbage collected.

By contrast, native WeakMaps hold "weak" references to key objects. As such native WeakMaps do not prevent garbage collection, which eventually removes references to the key object. "Weak" references also avoid preventing garbage collection of values in the map. WeakMaps can be particularly useful constructs when mapping keys to information about the key that is valuable only if the key has not been garbage collected.

WeakMap There is no method to obtain a list of the keys. If there was, the list would depend on the state of garbage collection, introducing non-determinism. If you want to have a list of keys, you should use a Map.

Constructor

WeakMap()
Creates a new WeakMap object.

Instance methods

WeakMap.prototype.delete(key)
Removes any value associated to the key. WeakMap.prototype.has(key) will return false afterwards.

WeakMap.prototype.get(key)
Returns the value associated to the key, or undefined if there is none.

WeakMap.prototype.has(key)
Returns a Boolean asserting whether a value has been associated to the key in the WeakMap object or not.

WeakMap.prototype.set(key, value)
Sets the value for the key in the WeakMap object. Returns the WeakMap object.

Examples

Using WeakMap

const wm1 = new WeakMap(),
      wm2 = new WeakMap(),
      wm3 = new WeakMap();
const o1 = {},
      o2 = function() {},
      o3 = window;

wm1.set(o1, 37);
wm1.set(o2, 'azerty');
wm2.set(o1, o2); // a value can be anything, including an object or a function
wm2.set(o3, undefined);
wm2.set(wm1, wm2); // keys and values can be any objects. Even WeakMaps!

wm1.get(o2); // "azerty"
wm2.get(o2); // undefined, because there is no key for o2 on wm2
wm2.get(o3); // undefined, because that is the set value

wm1.has(o2); // true
wm2.has(o2); // false
wm2.has(o3); // true (even if the value itself is 'undefined')

wm3.set(o1, 37);
wm3.get(o1); // 37

wm1.has(o1); // true
wm1.delete(o1);
wm1.has(o1); // false

Implementing a WeakMap-like class with a .clear() method

class ClearableWeakMap {
  constructor(init) {
    this._wm = new WeakMap(init);
  }
  clear() {
    this._wm = new WeakMap();
  }
  delete(k) {
    return this._wm.delete(k);
  }
  get(k) {
    return this._wm.get(k);
  }
  has(k) {
    return this._wm.has(k);
  }
  set(k, v) {
    this._wm.set(k, v);
    return this;
  }
}

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-weakmap-objects

Browser compatibility

Desktop

Mobile

Chrome

Edge

Firefox

Internet Explorer

Opera

Safari

WebView Android

Chrome Android

Firefox for Android

Opera Android

Safari on IOS

Samsung Internet

WeakMap

36

12

6

11

23

8

37

36

6

24

8

3.0

WeakMap

36

12

6

11

23

8

37

36

6

24

8

3.0

clear

36-43

No

20-46

11

25-30

8-9

37-43

36-43

20-46

25-30

8-9

3.0-4.0

delete

36

12

6

Prior to Firefox 38, this method threw a TypeError when the key parameter was not an object. This has been fixed in version 38 and later to return false as per the ES2015 standard.

11

23

8

37

36

6

Prior to Firefox 38, this method threw a TypeError when the key parameter was not an object. This has been fixed in version 38 and later to return false as per the ES2015 standard.

24

8

3.0

get

36

12

6

Prior to Firefox 38, this method threw a TypeError when the key parameter was not an object. However, the ES2015 specification specifies to return undefined instead. Furthermore, WeakMap.prototype.get accepted an optional second argument as a fallback value, which is not part of the standard. Both non-standard behaviors are removed in version 38 and higher.

11

23

8

37

36

6

Prior to Firefox 38, this method threw a TypeError when the key parameter was not an object. However, the ES2015 specification specifies to return undefined instead. Furthermore, WeakMap.prototype.get accepted an optional second argument as a fallback value, which is not part of the standard. Both non-standard behaviors are removed in version 38 and higher.

24

8

3.0

has

36

12

6

Prior to Firefox 38, this method threw a TypeError when the key parameter was not an object. This has been fixed in version 38 and later to return false as per the ES2015 standard.

11

23

8

37

36

6

Prior to Firefox 38, this method threw a TypeError when the key parameter was not an object. This has been fixed in version 38 and later to return false as per the ES2015 standard.

24

8

3.0

set

36

12

6

Prior to Firefox 38, this method threw a TypeError when the key parameter was not an object. This has been fixed in version 38 and later to return false as per the ES2015 standard.

11

Returns 'undefined' instead of the 'Map' object.

23

8

37

36

6

Prior to Firefox 38, this method threw a TypeError when the key parameter was not an object. This has been fixed in version 38 and later to return false as per the ES2015 standard.

24

8

3.0

See also

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap

WeakSet

The WeakSet object lets you store weakly held objects in a collection.

Description

WeakSet objects are collections of objects. Just as with Sets, each object in a WeakSet may occur only once; all objects in a WeakSet's collection are unique.

The main differences to the Set object are:

  • WeakSets are collections of objects only. They cannot contain arbitrary values of any type, as Sets can.
  • The WeakSet is weak, meaning references to objects in a WeakSet are held weakly. If no other references to an object stored in the WeakSet exist, those objects can be garbage collected. Note: This also means that there is no list of current objects stored in the collection. WeakSets are not enumerable.

Use case: Detecting circular references

Functions that call themselves recursively need a way of guarding against circular data structures by tracking which objects have already been processed.

WeakSets are ideal for this purpose:

// Execute a callback on everything stored inside an object
function execRecursively(fn, subject, _refs = null){
  if(!_refs)
    _refs = new WeakSet();

  // Avoid infinite recursion
  if(_refs.has(subject))
    return;

  fn(subject);
  if("object" === typeof subject){
    _refs.add(subject);
    for(let key in subject)
      execRecursively(fn, subject[key], _refs);
  }
}

const foo = {
  foo: "Foo",
  bar: {
    bar: "Bar"
  }
};

foo.bar.baz = foo; // Circular reference!
execRecursively(obj => console.log(obj), foo);

Here, a WeakSet is created on the first run, and passed along with every subsequent function call (using the internal _refs parameter).

The number of objects or their traversal order is immaterial, so a WeakSet is more suitable (and performant) than a Set for tracking object references, especially if a very large number of objects is involved.

Constructor

WeakSet()
Creates a new WeakSet object.

Instance methods

WeakSet.prototype.add(value)
Appends value to the WeakSet object.

WeakSet.prototype.delete(value)
Removes value from the WeakSet. WeakSet.prototype.has(value) will return false afterwards.

WeakSet.prototype.has(value)
Returns a boolean asserting whether value is present in the WeakSet object or not.

Examples

Using the WeakSet object

const ws = new WeakSet();
const foo = {};
const bar = {};

ws.add(foo);
ws.add(bar);

ws.has(foo);    // true
ws.has(bar);    // true

ws.delete(foo); // removes foo from the set
ws.has(foo);    // false, foo has been removed
ws.has(bar);    // true, bar is retained

Note that foo !== bar. While they are similar objects, *they are not the same object*. And so they are both added to the set.

Specifications

Specification
ECMAScript (ECMA-262)

The definition of 'WeakSet' in that specification.

Browser compatibility

Desktop

Mobile

Chrome

Edge

Firefox

Internet Explorer

Opera

Safari

WebView Android

Chrome Android

Firefox for Android

Opera Android

Safari on IOS

Samsung Internet

WeakSet

36

12

34

No

23

9

37

36

34

24

9

3.0

WeakSet

36

12

34

No

23

9

37

36

34

24

9

3.0

add

36

12

34

No

23

9

37

36

34

24

9

3.0

clear

36-41

No

34-46

No

23-28

No

37-41

36-41

34-46

24-28

No

3.0-4.0

delete

36

12

34

No

23

9

37

36

34

24

9

3.0

has

36

12

34

No

23

9

37

36

34

24

9

3.0

See also

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet

WebAssembly

The WebAssembly JavaScript object acts as the namespace for all WebAssembly-related functionality.

Unlike most other global objects, WebAssembly is not a constructor (it is not a function object). You can compare it to Math, which is also a namespace object for mathematical constants and functions, or to Intl which is the namespace object for internationalization constructors and other language-sensitive functions.

Description

The primary uses for the WebAssembly object are:

Constructor properties

WebAssembly.CompileError()
Indicates an error during WebAssembly decoding or validation.

WebAssembly.Global()
Represents a global variable instance, accessible from both JavaScript and importable/exportable across one or more WebAssembly.Module instances. This allows dynamic linking of multiple modules.

WebAssembly.Instance()
Is a stateful, executable instance of a WebAssembly.Module

WebAssembly.LinkError()
Indicates an error during module instantiation (besides traps from the start function).

WebAssembly.Memory()
An object whose buffer property is a resizable ArrayBuffer that holds the raw bytes of memory accessed by a WebAssembly Instance.

WebAssembly.Module()
Contains stateless WebAssembly code that has already been compiled by the browser and can be efficiently shared with Workers, and instantiated multiple times.

WebAssembly.RuntimeError()
Error type that is thrown whenever WebAssembly specifies a trap.

WebAssembly.Table()
An array-like structure representing a WebAssembly Table, which stores function references.

Static methods

WebAssembly.instantiate()
The primary API for compiling and instantiating WebAssembly code, returning both a Module and its first Instance.

WebAssembly.instantiateStreaming()
Compiles and instantiates a WebAssembly module directly from a streamed underlying source, returning both a Module and its first Instance.

WebAssembly.compile()
Compiles a WebAssembly.Module from WebAssembly binary code, leaving instantiation as a separate step.

WebAssembly.compileStreaming()
compiles a WebAssembly.Module directly from a streamed underlying source, leaving instantiation as a separate step.

WebAssembly.validate()
Validates a given typed array of WebAssembly binary code, returning whether the bytes are valid WebAssembly code (true) or not (false).

Examples

Stream a .wasm module then compile and instantiate it

The following example (see our instantiate-streaming.html demo on GitHub, and view it live also) directly streams a .wasm module from an underlying source then compiles and instantiates it, the promise fulfilling with a ResultObject. Because the instantiateStreaming() function accepts a promise for a Response object, you can directly pass it a WindowOrWorkerGlobalScope.fetch() call, and it will pass the response into the function when it fulfills.

var importObject = { imports: { imported_func: arg => console.log(arg) } };

WebAssembly.instantiateStreaming(fetch('simple.wasm'), importObject)
.then(obj => obj.instance.exports.exported_func());

The ResultObject's instance member is then accessed, and the contained exported function invoked.

Specifications

Specification
WebAssembly JavaScript Interface (WebAssembly JavaScript Interface)

#webassembly-namespace

Browser compatibility

Desktop

Mobile

Chrome

Edge

Firefox

Internet Explorer

Opera

Safari

WebView Android

Chrome Android

Firefox for Android

Opera Android

Safari on IOS

Samsung Internet

CompileError

57

16

52

Disabled in the Firefox 52 Extended Support Release (ESR).

No

44

11

57

57

52

Disabled in the Firefox 52 Extended Support Release (ESR).

43

11

7.0

Global

69

79

62

No

No

13.1

69

69

62

No

13.4

10.0

Instance

57

16

52

Disabled in the Firefox 52 Extended Support Release (ESR).

No

44

11

57

57

52

Disabled in the Firefox 52 Extended Support Release (ESR).

43

11

7.0

LinkError

57

16

52

Disabled in the Firefox 52 Extended Support Release (ESR).

No

44

11

57

57

52

Disabled in the Firefox 52 Extended Support Release (ESR).

43

11

7.0

Memory

57

16

52

Disabled in the Firefox 52 Extended Support Release (ESR).

No

44

11

57

57

52

Disabled in the Firefox 52 Extended Support Release (ESR).

43

11

7.0

Module

57

16

52

Disabled in the Firefox 52 Extended Support Release (ESR).

No

44

11

57

57

52

Disabled in the Firefox 52 Extended Support Release (ESR).

43

11

7.0

RuntimeError

57

16

52

Disabled in the Firefox 52 Extended Support Release (ESR).

No

44

11

57

57

52

Disabled in the Firefox 52 Extended Support Release (ESR).

43

11

7.0

Table

57

16

52

Disabled in the Firefox 52 Extended Support Release (ESR).

No

44

11

57

57

52

Disabled in the Firefox 52 Extended Support Release (ESR).

43

11

7.0

WebAssembly

57

16

52

Disabled in the Firefox 52 Extended Support Release (ESR).

No

44

11

57

57

52

Disabled in the Firefox 52 Extended Support Release (ESR).

43

11

7.0

compile

57

16

52

Disabled in the Firefox 52 Extended Support Release (ESR).

No

44

11

57

57

52

Disabled in the Firefox 52 Extended Support Release (ESR).

43

11

7.0

compileStreaming

61

16

58

No

47

No

61

61

58

45

No

8.0

instantiate

57

16

52

Disabled in the Firefox 52 Extended Support Release (ESR).

No

44

11

57

57

52

Disabled in the Firefox 52 Extended Support Release (ESR).

43

11

7.0

instantiateStreaming

61

16

58

No

47

No

61

61

58

45

No

8.0

validate

57

16

52

Disabled in the Firefox 52 Extended Support Release (ESR).

No

44

11

57

57

52

Disabled in the Firefox 52 Extended Support Release (ESR).

43

11

7.0

See also

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly

while

The while statement creates a loop that executes a specified statement as long as the test condition evaluates to true. The condition is evaluated before executing the statement.

Syntax

while (condition)
  statement

condition
An expression evaluated before each pass through the loop. If this condition evaluates to true, statement is executed. When condition evaluates to false, execution continues with the statement after the while loop.

statement
An optional statement that is executed as long as the condition evaluates to true. To execute multiple statements within the loop, use a block statement ({ ... }) to group those statements.

Note: Use the break statement to stop a loop before condition evaluates to true.

Examples

Using while

The following while loop iterates as long as n is less than three.

var n = 0;
var x = 0;

while (n < 3) {
  n++;
  x += n;
}

Each iteration, the loop increments n and adds it to x. Therefore, x and n take on the following values:

  • After the first pass: n = 1 and x = 1
  • After the second pass: n = 2 and x = 3
  • After the third pass: n = 3 and x = 6

After completing the third pass, the condition n < 3 is no longer true, so the loop terminates.

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-while-statement

Browser compatibility

Desktop

Mobile

Chrome

Edge

Firefox

Internet Explorer

Opera

Safari

WebView Android

Chrome Android

Firefox for Android

Opera Android

Safari on IOS

Samsung Internet

while

1

12

1

3

3

1

1

18

4

10.1

1

1.0

See also

© 2005–2021 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/while

with

**Warning:**Use of the with statement is not recommended, as it may be the source of confusing bugs and compatibility issues. See the "Ambiguity Contra" paragraph in the "Description" section below for details.

The with statement extends the scope chain for a statement.

Syntax

with (expression)
  statement

expression
Adds the given expression to the scope chain used when evaluating the statement. The parentheses around the expression are required.

statement
Any statement. To execute multiple statements, use a block statement ({ ... }) to group those statements.

Description

JavaScript looks up an unqualified name by searching a scope chain associated with the execution context of the script or function containing that unqualified name. The 'with' statement adds the given object to the head of this scope chain during the evaluation of its statement body. If an unqualified name used in the body matches a property in the scope chain, then the name is bound to the property and the object containing the property. Otherwise a ReferenceError is thrown.

Note: Using with is not recommended, and is forbidden in ECMAScript 5 strict mode. The recommended alternative is to assign the object whose properties you want to access to a temporary variable.

Performance pro & contra

Pro: The with statement can help reduce file size by reducing the need to repeat a lengthy object reference without performance penalty. The scope chain change required by 'with' is not computationally expensive. Use of 'with' will relieve the interpreter of parsing repeated object references. Note, however, that in many cases this benefit can be achieved by using a temporary variable to store a reference to the desired object.

Contra: The with statement forces the specified object to be searched first for all name lookups. Therefore all identifiers that aren't members of the specified object will be found more slowly in a 'with' block. Where performance is important, 'with' should only be used to encompass code blocks that access members of the specified object.

Ambiguity contra

Contra: The with statement makes it hard for a human reader or JavaScript compiler to decide whether an unqualified name will be found along the scope chain, and if so, in which object. So given this example:

function f(x, o) {
  with (o) {
    console.log(x);
  }
}

Only when f is called is x either found or not, and if found, either in o or (if no such property exists) in f's activation object, where x names the first formal argument. If you forget to define x in the object you pass as the second argument, or if there's some similar bug or confusion, you won't get an error -- just unexpected results.

Contra: Code using with may not be forward compatible, especially when used with something other than a plain object. Consider this example:

function f(foo, values) {
  with (foo) {
    console.log(values);
  }
}

If you call f([1,2,3], obj) in an ECMAScript 5 environment, then the values reference inside the with statement will resolve to obj. However, ECMAScript 2015 introduces a values property on Array.prototype (so that it will be available on every array). So, in a JavaScript environment that supports ECMAScript 2015, the values reference inside the with statement could resolve to [1,2,3].values. However, in this particular example, Array.prototype has been defined with values in its Symbol.unscopables object. If it were not, one can see how this would be a difficult issue to debug.

Examples

Using with

The following with statement specifies that the Math object is the default object. The statements following the with statement refer to the PI property and the cos and sin methods, without specifying an object. JavaScript assumes the Math object for these references.

var a, x, y;
var r = 10;

with (Math) {
  a = PI * r * r;
  x = r * cos(PI);
  y = r * sin(PI / 2);
}

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-with-statement

Browser compatibility

Desktop

Mobile

Chrome

Edge

Firefox

Internet Explorer

Opera

Safari

WebView Android

Chrome Android

Firefox for Android

Opera Android

Safari on IOS

Samsung Internet

with

1

12

1

3

4

1

1

18

4

10.1

1

1.0

See also

© 2005–2021 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with

Atomics.xor()

The static Atomics``.xor() method computes a bitwise XOR with a given value at a given position in the array, and returns the old value at that position. This atomic operation guarantees that no other write happens until the modified value is written back.

Syntax

Atomics.xor(typedArray, index, value)

Parameters

typedArray
An integer typed array. One of Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, BigInt64Array, or BigUint64Array.

index
The position in the typedArray to compute the bitwise XOR.

value
The number to compute the bitwise XOR with.

Return value

The old value at the given position (typedArray[index]).

Exceptions

  • Throws a TypeError, if typedArray is not one of the allowed integer types.
  • Throws a RangeError, if index is out of bounds in the typedArray.

Description

The bitwise XOR operation yields 1, if a and b are different. The truth table for the XOR operation is:

aba ^ b
000
011
101
110

For example, a bitwise XOR of 5 ^ 1 results in 0100 which is 4 in decimal.

5  0101
1  0001
   ----
4  0100

Examples

Using xor

const sab = new SharedArrayBuffer(1024);
const ta = new Uint8Array(sab);
ta[0] = 5;

Atomics.xor(ta, 0, 1); // returns 5, the old value
Atomics.load(ta, 0);  // 4

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-atomics.xor

Browser compatibility

Desktop

Mobile

Chrome

Edge

Firefox

Internet Explorer

Opera

Safari

WebView Android

Chrome Android

Firefox for Android

Opera Android

Safari on IOS

Samsung Internet

xor

68

60-63

Chrome disabled SharedArrayBuffer on January 5, 2018 to help reduce the efficacy of speculative side-channel attacks. This was a temporary removal while mitigations were put in place.

79

16-17

Support was removed to mitigate speculative execution side-channel attacks (Windows blog).

78

57

Support was disabled by default to mitigate speculative execution side-channel attacks (Mozilla Security Blog).

55-57

46-55

No

No

10.1-11.1

60-63

Chrome disabled SharedArrayBuffer on January 5, 2018 to help reduce the efficacy of speculative side-channel attacks. This is intended as a temporary measure until other mitigations are in place.

60-63

Chrome disabled SharedArrayBuffer on January 5, 2018 to help reduce the efficacy of speculative side-channel attacks. This is intended as a temporary measure until other mitigations are in place.

57

Support was disabled by default to mitigate speculative execution side-channel attacks (Mozilla Security Blog).

55-57

46-55

No

10.3-11.3

No

Chrome disabled SharedArrayBuffer on January 5, 2018 to help reduce the efficacy of speculative side-channel attacks. This is intended as a temporary measure until other mitigations are in place.

See also

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/xor

yield

The yield keyword is used to pause and resume a generator function (function* or legacy generator function).

Syntax

[rv] = yield [expression]

expression Optional
Defines the value to return from the generator function via the iterator protocol. If omitted, undefined is returned instead.

rv Optional
Retrieves the optional value passed to the generator's next() method to resume its execution.

Description

The yield keyword pauses generator function execution and the value of the expression following the yield keyword is returned to the generator's caller. It can be thought of as a generator-based version of the return keyword.

yield can only be called directly from the generator function that contains it. It cannot be called from nested functions or from callbacks.

The yield keyword causes the call to the generator's next() method to return an IteratorResult object with two properties: value and done. The value property is the result of evaluating the yield expression, and done is false, indicating that the generator function has not fully completed.

Once paused on a yield expression, the generator's code execution remains paused until the generator's next() method is called. Each time the generator's next() method is called, the generator resumes execution, and runs until it reaches one of the following:

  • A yield, which causes the generator to once again pause and return the generator's new value. The next time next() is called, execution resumes with the statement immediately after the yield.
  • throw is used to throw an exception from the generator. This halts execution of the generator entirely, and execution resumes in the caller (as is normally the case when an exception is thrown).
  • The end of the generator function is reached. In this case, execution of the generator ends and an IteratorResult is returned to the caller in which the value is undefined and done is true.
  • A return statement is reached. In this case, execution of the generator ends and an IteratorResult is returned to the caller in which the value is the value specified by the return statement and done is true.

If an optional value is passed to the generator's next() method, that value becomes the value returned by the generator's current yield operation.

Between the generator's code path, its yield operators, and the ability to specify a new starting value by passing it to Generator.prototype.next(), generators offer enormous power and control.

Warning: Unfortunately, next() is asymmetric, but that can't be helped: It always sends a value to the currently suspended yield, but returns the operand of the following yield.

Examples

Using yield

The following code is the declaration of an example generator function.

function* countAppleSales () {
  let saleList = [3, 7, 5]
  for (let i = 0; i < saleList.length; i++) {
    yield saleList[i]
  }
}

Once a generator function is defined, it can be used by constructing an iterator as shown.

let appleStore = countAppleSales()  // Generator { }
console.log(appleStore.next())      // { value: 3, done: false }
console.log(appleStore.next())      // { value: 7, done: false }
console.log(appleStore.next())      // { value: 5, done: false }
console.log(appleStore.next())      // { value: undefined, done: true }

You can also send a value with next(value) into the generator. 'step' evaluates as a return value in this syntax [rv] = yield [expression]

function* counter(value) {
 let step;

 while (true) {
   step = yield ++value;

   if (step) {
     value += step;
   }
 }
}

const generatorFunc = counter(0);
console.log(generatorFunc.next().value);   // 1
console.log(generatorFunc.next().value);   // 2
console.log(generatorFunc.next().value);   // 3
console.log(generatorFunc.next(10).value); // 14
console.log(generatorFunc.next().value);   // 15
console.log(generatorFunc.next(10).value); // 26

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#prod-YieldExpression

Browser compatibility

Desktop

Mobile

Chrome

Edge

Firefox

Internet Explorer

Opera

Safari

WebView Android

Chrome Android

Firefox for Android

Opera Android

Safari on IOS

Samsung Internet

yield

39

12

26

["Starting with Firefox 33, the parsing of the yield expression has been updated to conform with the ES2015 specification.", "Starting with Firefox 29, an IteratorResult object returned for completed generator function."]

No

26

10

39

39

26

["Starting with Firefox 33, the parsing of the yield expression has been updated to conform with the ES2015 specification.", "Starting with Firefox 29, an IteratorResult object returned for completed generator function."]

26

10

4.0

See also

© 2005–2021 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield

yield*

The yield* is used to delegate to another generator or iterable object.

Syntax

 yield* expression;

expression
The expression which returns an iterable object.

Description

The yield* expression iterates over the operand and yields each value returned by it.

The value of yield* expression itself is the value returned by that iterator when it's closed (i.e., when done is true).

Examples

Delegating to another generator

In following code, values yielded by g1() are returned from next() calls just like those which are yielded by g2().

function* g1() {
  yield 2;
  yield 3;
  yield 4;
}

function* g2() {
  yield 1;
  yield* g1();
  yield 5;
}

const iterator = g2();

console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: 4, done: false}
console.log(iterator.next()); // {value: 5, done: false}
console.log(iterator.next()); // {value: undefined, done: true}

Other Iterable objects

Besides generator objects, yield* can also yield other kinds of iterables (e.g., arrays, strings, or arguments objects).

function* g3() {
  yield* [1, 2];
  yield* '34';
  yield* Array.from(arguments);
}

const iterator = g3(5, 6);

console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: "3", done: false}
console.log(iterator.next()); // {value: "4", done: false}
console.log(iterator.next()); // {value: 5, done: false}
console.log(iterator.next()); // {value: 6, done: false}
console.log(iterator.next()); // {value: undefined, done: true}

The value of yield* expression itself

yield* is an expression, not a statement—so it evaluates to a value.

function* g4() {
  yield* [1, 2, 3];
  return 'foo';
}

function* g5() {
  const g4ReturnValue = yield* g4();
  console.log(g4ReturnValue) // 'foo'
  return g4ReturnValue;
}

const iterator = g5();

console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false} done is false because g5 generator isn't finished, only g4
console.log(iterator.next()); // {value: 'foo', done: true}

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-generator-function-definitions-runtime-semantics-evaluation

Browser compatibility

Desktop

Mobile

Chrome

Edge

Firefox

Internet Explorer

Opera

Safari

WebView Android

Chrome Android

Firefox for Android

Opera Android

Safari on IOS

Samsung Internet

yield*

39

12

27

Starting with Firefox 33, the parsing of the yield expression has been updated to conform with the ES2015 specification.

No

26

10

39

39

27

Starting with Firefox 33, the parsing of the yield expression has been updated to conform with the ES2015 specification.

26

10

4.0

See also

© 2005–2021 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield\*

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment