js notes - bgoonz/BGOONZ_BLOG_2.0 GitHub Wiki


title: Variables chapter: Variables

Variables are declared with the var keyword. JavaScript is dynamically typed so every variable can hold a value of any data type.

Variables can be declared without an initial value.

Some example declarations:

var foo;
var bar = 42;
var foo, bar, baz;
var foo = 42,
    bar = 'baz',
    z;

Variables that don't explicitly get assigned an initial value have the value undefined.

ES2015

Since ES2015, let and const can be used in addition to var. We will learn how they differ from var later. For now, lets have a look how const differs from var or let: const can be assigned a value only once (constant).
Reassigning a value will either throw an error (in strict mode, see below) or is silently ignored:

const foo = 42;
foo = 21; // error or ignored

consts must be initialized with a value:

const foo; // error
foo = 42;

Variable names

Valid characters for variable names include a wide range of unicode characters. However, the name must start with a letter, _ or $. Not doing so will result in a syntax error.

Examples:

var π = 3.141;
var _foo = π;
var 0_bar = '...'; // Syntax error

Variable access

Trying to read an undeclared variable results in a runtime error:

var foo;
console.log(bar); // ReferenceError: bar is not defined.

However, writing to an undeclared variable is valid by default. It will create an implicit global variable and should thus be avoided:

function foo() {
    bar = 42;
}
foo();
console.log(bar); // no error

If code runs in strict mode, assigning to an undeclared variable throws an error.

Strict mode

Strict mode is a mode of evaluating JavaScript that enforces stricter rules. It was introduced to "deprecate" certain patterns/behaviors that are considered bad or confusing.

Strict mode can be enabled for a JavaScript or a function by putting

'use strict';

at the beginning of it.


title: Scope chapter: Scope

Unlike other programming languages, JavaScript only has function scope, not block scope. In the following example, all variables are visible throughout the function:

function foo() {
    var bar = 42;
    // loop
    for (var i = 0; i < 10; i++) {
        var j = i;
    }

    console.log(bar); // 42
    console.log(i); // 10
    console.log(j); // 9
}

In other languages, like Java, the variables i or j would not be available where the above code tries to access them.

ES2015

The big difference between let, const, and var is that let and const are [block scoped][block scope]. If we would use let instead of var in the above example, we would get the following result:

function foo() {
    let bar = 42; // or var or const, doesn't matter
    // loop
    for (let i = 0; i < 10; i++) {
        // i is scoped to the loop body block
        let j = i; // j is scoped to the loop body block
    }

    console.log(bar); // 42
    console.log(i); // ReferenceError
    console.log(j); // ReferneceError
}

toc: What is this? chapter: this style: | h1 { text-align: center }

What is this?

this is a special "variable" which implicitly exists in every function. It can be thought of being similar to Java's this and Python's self, but it's much more flexible than that.

Important: The value of this is determined when the function is called, not when the function is defined.

Given the following function:

function foo() {
    console.log(this);
}

these would be the values of this if called in those specific ways:

// "normal call": global object / window in browsers
//                undefined in strict mode
foo();

// as object "method": to the object
var obj = { method: foo };
obj.method();

// via .call / .apply: To the value passed as first argument
foo.call(bar);

title: JavaScript Basics toc: Title chapter: Intro layout: Center style: | .exerslide-slide .Center-wrapper { text-align: left; } .exerslide-slide h1 { color: #444; font-size: 400%; margin-bottom: 50px; text-align: center; } scale: content_width: 39 column_width: 0.6

A quick introduction to basic and important concepts of JavaScript

Use the arrow keys (←, →) to navigate through the page.

You should use Google Chrome and make yourself familiar with the [developer tools][], especially with the console. You will need it for the exercises.


Contribute

Found a problem with style or content? Or do you have suggestions for improving the content? Please [file an issue on GitHub][jsbasics-issues].


title: Booleans, numbers and strings

The Boolean data type has two values, true and false.

var foo = true;
var bar = false;

Numbers are double precision floating point numbers, following the IEEE 754 standard

This makes it very easy to work with them, since you don't have to differentiate between integer values and floating point values.

There are various ways that numeric value can be expressed:

var x = 5; // "integer"
var y = -4.2; // "float"
var z = 5e3; // = 5 * 10^3

An issue with floating point numbers is the loss of precision, which of course occurs in JavaScript as well:

0.1 + 0.2; // 0.30000000000000004

The maximum integer value that can be used without loss of precision is 253.

Math.pow(2, 53); // 9007199254740992
Math.pow(2, 53) + 1; // 9007199254740992

Strings are sequences of unicode characters and can either be delimited with a single or double quotation mark. Unlike in other languages, such as PHP, both are interpreted in the exact same way.

Example:

var foo = 'bar';
var bar = 'baz';

title: Demo layout_data: description: Run the code and have a look at the output. Is it what you expect? Try some other values / operators and look at the output (remember to open the console).

var a = 10; var b = 5; var c = "1";

log(a + b); log(a + c); log(b + Number(c));


title: Constructor functions chapter: Constructors/Classes

JavaScript doesn't have classes like class-based OOP languages have, but it has something similar: constructor functions.

Constructor functions are functions which construct objects. Technically every function can be used as a constructor function, it just has to be called with the new operator:

function Person(name) {
    this.name = name;
}

var felix = new Person('Felix');
console.log(felix.name);

Inside the constructor function, this refers to a new, empty object. The result of the whole new expression (new Person(...)) is that object. You can think about it as if the function would implicitly return this;.

Calling a function with new has another effect: The prototype of the new object is the object referred to by the function's prototype property.

Example:

function Person(name) {
    this.name = name;
}
Person.prototype.sayName = function () {
    return this.name;
};

var felix = new Person('Felix');
console.log(felix.sayName());

Given the example above, use console.dir(felix); to get a better understanding of the structure of the object (including it's prototype chain).


title: Exercise layout_data: description: | Create a local variable with name foo and value 42. Use log(foo) to log the value of foo. Remember to open your browser's developer tools to view the log output. assertion: | assert( /var foo\s*=.+;?$/m.test(source), "It doesn't look like you have declared a variable (hint: var)." ); assert(output[0] === 42, "Don't forget to log the value");

// Create variable

// log(foo);


title: Hoisting

This behavior becomes more understandable after we introduce hoisting. Before a JavaScript function is even executed, the engine finds all variable and function declarations and creates a binding for them in the functions scope.

Thus, the example of the previous slide is equivalent to the following:

function foo() {
    var bar, i, j;

    bar = 42;
    // loop
    for (i = 0; i < 10; i++) {
        j = i;
    }

    console.log(bar); // 42
    console.log(i); // 10
    console.log(j); // 9
}

Note how all variable declarations are put at the top of the function. The value will still be assigned only when the execution reaches the line of the assignment expression.

One of the practical implications of the hoisting concept is mutually recursive functions. Consider the following example:

function isEven(n) {
    if (n == 0) {
        return true;
    }
    return isOdd(n - 1);
}

// Normally may call `isEven` even though it's mutually
// dependent on the `isOdd` which is defined below.
console.log(isEven(2)); // true

function isOdd(n) {
    if (n == 0) {
        return false;
    }
    return isEven(n - 1);
}

To get more details on hoisting see this article.


toc: this - an example style: | h1 { text-align: center }

this - an example

function say() {
    console.log('My name is ' + this.name);
}

var felix = {
    name: 'Felix',
    sayName: say
};

var sarah = {
    name: 'Sarah',
    sayName: say
};

felix.sayName(); // My name is Felix
sarah.sayName(); // My name is Sarah
say.call({ name: 'Anonymous' }); // My name is Anonymous
say(); // My names is undefined

In this example we define a single function that uses this internally. The function is then assigned to different objects as property. The output the function produces depends on which object the function is called (how it is called).


title: What this presentation is not about layout: Center style: | .exerslide-slide .Center-wrapper { text-align: left; } .exerslide-slide h1 { text-align: center; }

JavaScript is predominantly run in browsers to make websites interactive. In order to do that, the browser provides access to other technologies, such as [CSS][] and the [DOM][].

This presentation is exclusively about JavaScript, the language, not the environment in which the JavaScript code runs!


title: Exercise layout_data: description: Create three variables x, y, z, where x contains a string value, y a number and z a boolean value. Log the values with log. assertion: | assert( output.some(function(x) { return typeof x === 'string' }), 'Your log must contain a string.' ); assert( output.some(function(x) { return typeof x === 'number' }), 'Your log must contain a number.' ); assert( output.some(function(x) { return typeof x === 'boolean' }), 'Your log must contain a boolean.' );

// Hint: You can pass multiple arguments to log: // log(a, b)


toc: "ES6's class declarations"

Syntactic sugar: ES6's class declarations

Setting up more complex constructor functions with their prototypes can be cumbersome. For that reason ES2015 introduced a new syntax. With the syntax, the example from the previous slide would look like

class Person {
    constructor(name) {
        this.name = name;
    }

    sayName() {
        return name;
    }
}

var felix = new Person('Felix');

I want to be very clear that this is mostly just syntactic sugar. While there are some differences between class declarations and constructor functions + prototype, the underlying paradigm (prototypes) does not change.


title: Comparison operators

As already established at the beginning, JavaScript is dynamically typed. It also performs type conversion, if a specific data type is expected and not provided. For example in a * b, the values of a and b will be converted to numbers first.

Even though there are well defined rules for converting one data type into another, these rules can be quite surprising.

What does this have to do with comparison? JavaScript has two kind of comparison operators:

  • Loose comparison (a == b, a != b)
  • Strict comparison (a === b, a !== b)

The difference is that loose comparison will convert both values to the same data type if they are of different data types. Strict comparison immediately returns false if both values don't have the same type.

Examples:

'42' == 42; // true
(('42' ===
    (42)[ // false
        // Objects are compared by reference
        (1, 2)
    ]) ==
    [1, 2][(1, 2)]) === // false
    [1, 2]; // false

The following tool visualizes the steps of the abstract equality comparison algorithm, which is used for loose comparison.

You can select some predefined examples and see which steps are performed during the comparison. The results will probably surprise you. You can also provide your own values.

[
  ["[1,2]", "'1,2'"],
  ["[0]", "false"],
  ["'\\n'", "false"],
  ["'0XA19'", "2585"]
]

Also have a look at this table to get a quick overview of the differences between == and ===.

The above examples hopefully showed you that loose comparison isn't that "simple" and it's not always clear what ends up being compared in the end. For that reason you should follow this advice:

You should always use strict comparison, unless you explicitly want to make use of the type conversion (i.e. you know what you are doing).

If you write an API, make it clear which data type it expects (e.g. through comments).


title: ES5, ES2015 and beyond layout: Center

style: | .exerslide-slide .Center-wrapper { text-align: left; } .exerslide-slide h1 { text-align: center; }

This tutorial primarily focuses on JavaScript following the [ECMAScript 5][es5] (ES5) specification. [ES2015][] (also known as ES6) was released in 2015 and brings many new features to the language, including new syntax constructs.

While this tutorial won't go into detail about new features in ES2015 and newer versions, it will point differences to/alternatives for certain ES5 features if they exist.


title: Demo layout_data: description: Which value does this code log and why? Think about the answer before you run the code.

var bar = 42; function foo() { log(bar); var bar = 21; log(bar); } foo();


title: Exercise layout_data: description: Which value does the code log and why? How can it be changed to log the value of obj.foo? assertion: | assert(output[0] === 42, 'The code should only log 42'); assert(/log\s*(\sthis.foo\s)/.test(source), "Looks like you tried to be clever. Don't modify log(this.foo).");

var obj = { foo: 42, bar: function () { log(this.foo); } };

var foo = obj.bar; foo();


title: Closures

Wikipedia describes closures as:

In programming languages, a closure (also lexical closure or function closure) is a function or reference to a function together with a referencing environment — a table storing a reference to each of the non-local variables (also called free variables or upvalues) of that function.

According to this definition, every function in JavaScript is a closure, because every function has an (internal) reference to the environment it was created in. The simplest example is:

var foo = 42;

function bar() {
    console.log(foo);
}

Here the function bar has access to foo, which is defined outside of it.

Important: The value of a free variable is determined when the function is executed, not when the function is defined. Read the previous sentence three times to make sure you really understand what it implies.


title: Exercise layout_data: description: Run the code and have a look at the output. Is it what you expect? What are reasons for this output? Modify the code, so that it prints the result you would expect. assertion: | var values = [" ", "0", 0];

    var c = 1;
    for (var i = 0, l = values.length; i < l; i++) {
      for (var j = i; j <  l; j++) {
        var expectedResult = values[i] === values[j];
        assert(
          expectedResult === output[c],
          'Comparing ' +  JSON.stringify(values[i]) + ' and ' +
          JSON.stringify(values[j]) + ' should yield ' + expectedResult.toString() +
          ' not ' + output[c]
        );
        c += 2;
      }
    }

var values = [" ", "0", 0];

for (var i = 0, l = values.length; i < l; i++) { for (var j = i; j < l; j++) { log( JSON.stringify(values[i]) + ' == ' + JSON.stringify(values[j]) + ': ', values[i] == values[j] ); } }


title: null and undefined

JavaScript has two data types to express the absence of a value, null and undefined.

null has the only value null and undefined has the only value undefined.

The difference between those two is subtle and is best explained by how to use them:

  • undefined is the value JavaScript itself uses to indicate the absence of a value.
  • null is the value the engineer should use to indicate the absence of a value.

Examples:

var foo; // no value is assigned, foo has the value undefined
var bar = null; // bar is explicitly set to null
console.log(foo); // logs "undefined"
console.log(bar); // logs "null"

There are other native occurrence of undefined which we will mention later.

Remember: A variable that doesn't exist cannot be accessed at all (it will throw a reference error). Instead of saying "the variable is undefined" we rather say "the variable is not declared" to avoid confusion.

var foo;
console.log(foo); // logs `undefined`
console.log(bar); // reference error

title: Demo layout_data: description: Which value does this code log and why? Think about the solution before you run the code.

var foo = 42; function bar() { log(foo); } foo = 21; bar();


title: Exercise layout_data: description: Which values does this code log and why? Modify the code so that it logs the values as "expected". assertion: assert( output.every(function(x, i) { return x === i; }), 'The code should output the loop variable of each iteration, i.e. 0, 1, 2' );

var functionArray = []; for (var i = 0; i < 3; i++) { functionArray[i] = function() { log(i); }; }

for (var j = 0; j < 3; j++) { functionArrayj; }


title: Exercise layout_data: description: Log the values null and undefined. assertion: | assert( output.some(function(x) { return x === null }), 'Your log must contain null.' ); assert( output.some(function(x) { return x === void 0; }), 'Your log must contain undefined.' ); assert( source.indexOf('undefined') === -1, 'Try to log undefined without writing it in the source code.' );


title: Property access

Properties of objects can be accessed in two ways:

  • Dot notation (obj.prop)
  • Bracket notation (obj["prop"])

You should always prefer dot notation, unless you have to use bracket notation. This could be if the property name is not a valid identifier or if it comes from a variable. You can use any expression inside the brackets.

Examples:

obj['test-field']; // test-field is not a valid identifier
var field = 'test';
obj[field];
obj['example' + i];

Because you can only use dot notation if the property name is a valid identifier name, array objects can only be accessed via bracket notation, arr[0], not dot notation, a.0.


You can assign to properties by putting the member expression on the left hand side of an assignment expression:

obj.prop = value;

If you have nested objects/arrays, you simply use a valid property accessor repeatedly:

var obj = { foo: { bar: [42, 21] } };
console.log(obj.foo.bar[0]); // which is evaluated as ((obj.foo).bar)[0]

Accessing a non existing property does not throw an error, it returns undefined:

var obj = {};
console.log(obj.foo);

title: Objects

Everything else besides primitive data type values is an object.

Objects are key-value stores, more specifically stringkey-value stores. The "keys" of an object are called properties.

The syntax to create a plain object is {key: value, ...}, which is called an object literal. For example:

var obj = {
    foo: 'bar',
    baz: 42
};

Note that the above example doesn't use quotation marks around the property names. In an object literal, quotation marks can be be omitted if the property name would also be a valid variable name. If not, they need to be quoted. Number literals are valid an object literal as well.

Here are some more examples of valid and invalid property names in object literals:

var obj = {
  foo: 0,        // valid, could be variable name
  'bar': 0,      // string literals are always valid
  123: 0,        // number literals are always valid
  1.5: 0,        // ^
  foo-bar: 0,    // invalid, would not be a valid variable name
  'foo-bar': 0,  // string literals are alwaus valid
};

Important: No matter which value or syntax you use for a property name, the value will always be converted to a string.

ES2015

ES2015 adds two extensions to object values and object literals:

  • Symbols are can be used as property names. They are not converted to strings.

  • Object literals can contain [computed property names][computed properties]:

    var foo = 42;
    var obj = {
        [foo]: 0
    };
    // creates {42: 0}

References

Just like in Java and other object-oriented programming languages, objects are represented as references. That means if a variable has an object as a value, it really has a reference to that object.

var user = {name: 'Tom'}:

:::ascii

                         ┌──────────────┐
┌─────┬──────────┐       │  Object#123  │
│user │ ref:123 ◆┼──────▶├──────┬───────┤
└─────┴──────────┘       │ name │ "Tom" │
                         └──────┴───────┘

:::

Assigning the value to another variable makes both variables point to the same object:

var owner = user;

:::ascii

┌─────┬──────────┐       ┌──────────────┐
│user │ ref:123 ◆┼──┐    │  Object#123  │
├─────┼──────────┤  ├───▶├──────┬───────┤
│owner│ ref:123 ◆┼──┘    │ name │ "Tom" │
└─────┴──────────┘       └──────┴───────┘

:::

Assigning to user.name will therefore also "change" owner.name:

user.name = 'Joe';
console.log(user.name, owner.name);
// Joe, Joe

:::ascii

┌─────┬──────────┐       ┌──────────────┐
│user │ ref:123 ◆┼──┐    │  Object#123  │
├─────┼──────────┤  ├───▶├──────┬───────┤
│owner│ ref:123 ◆┼──┘    │ name │ "Joe" │
└─────┴──────────┘       └──────┴───────┘

:::

But assigning a new value to either user or owner will result in only that variable referring to the new value. The other variable will still refer to the same value.

owner = { name: 'Kim' };

:::ascii

                         ┌──────────────┐
                         │  Object#123  │
                    ┌───▶├──────┬───────┤
┌─────┬──────────┐  │    │ name │ "Joe" │
│user │ ref:123 ◆┼──┘    └──────┴───────┘
├─────┼──────────┤
│owner│ ref:456 ◆┼──┐    ┌──────────────┐
└─────┴──────────┘  │    │  Object#456  │
                    └───▶├──────┬───────┤
                         │ name │ "Kim" │
                         └──────┴───────┘

:::


The JavaScript standard defines a couple of built-in objects with additional properties and special internal behavior, must notably arrays and functions, which are explained in the next slides.


title: Exercise layout_data: description: Log the two properties of the object using dot and bracket notation. assertion: assert( source.indexOf('obj.foo') > -1, 'Access property foo with dot notation' ); assert( /obj[(42|'42'|"42")]/.test(source), 'How exactly did you want to access property 42?' );

var obj = {foo: 'bar', 42: 'answer'};


title: Prototypes (1)

You may have heard that JavaScript is a "prototype-based language", unlike other languages, such as Java, which are "class-based languages".

What exactly is a prototype?

In short: A prototype is just another object. If an object A has this special connection to object B, then we say that "B is the prototype of A".

In addition to having "external" properties that can be accessed from code, objects also have internal/private properties/state. These cannot be accessed from code and their concrete implementation depends on the JavaScript engine.

Every object has an internal property [[Prototype]] (internal properties are usually denoted with [[...]] around the name). This property points to another object.

:::ascii

┌───────────────────────┐       ┌────────────────────────┐
│           A           │       │           B            │
├───────────────┬───────┤       ├───────────────┬────────┤
│ name          │ "Tom" │   ┌──▶│ toString      │ <func> │
├───────────────┼───────┤   │   ├───────────────┼────────┤
│ [[Prototype]] │   ◆───┼───┘   │ [[Prototype]] │  null  │
└───────────────┴───────┘       └───────────────┴────────┘

:::

Multiple objects can have the same prototype.

:::ascii

┌───────────────────────┐       ┌────────────────────────┐
│           A           │       │           B            │
├───────────────┬───────┤       ├───────────────┬────────┤
│ name          │ "Tom" │   ┌──▶│ toString      │ <func> │
├───────────────┼───────┤   │   ├───────────────┼────────┤
│ [[Prototype]] │   ◆───┼───┘   │ [[Prototype]] │  null  │
└───────────────┴───────┘       └───────────────┴────────┘
                                             ▲
┌───────────────────────┐                    │
│           C           │                    │
├───────────────┬───────┤                    │
│ time          │ "day" │                    │
├───────────────┼───────┤                    │
│ [[Prototype]] │   ◆───┼────────────────────┘
└───────────────┴───────┘

:::

Since a prototype is an object, it might itself have a prototype, which may have a prototype, and so forth.

:::ascii

┌───────────────────┐
│         A         │
├───────────────┬───┤
│ [[Prototype]] │ ◆─┼────┐
└───────────────┴───┘    │
                         ▼
               ┌───────────────────┐
               │         B         │
               ├───────────────┬───┤
               │ [[Prototype]] │ ◆─┼────┐
               └───────────────┴───┘    │
                                        ▼
                              ┌───────────────────┐
                              │         C         │
                              ├───────────────┬───┤
                              │ [[Prototype]] │ ◆─│─ ─ ─ ▷
                              └───────────────┴───┘

:::

This is called the prototype chain. Almost all objects have the same object at the end of the prototype chain, which doesn't have a prototype itself.

An object created using literal notation will have the object Object.prototype as its prototype. You can verify this using the following commands:

var testObject = {};
Object.getPrototypeOf(testObject) === Object.prototype; // true

:::ascii

                            ┌────────────────────────┐
┌───────────────────┐       │    Object.prototype    │
│    testObject     │       ├───────────────┬────────┤
├───────────────┬───┤       │ toString      │ <func> │
│ [[Prototype]] │ ◆─┼──────▶├───────────────┼────────┤
└───────────────┴───┘       │ hasOwnProperty│ <func> │
                            ├───────────────┼────────┤
                            │ [[Prototype]] │  null  │
                            └───────────────┴────────┘

:::

In order to create an object with an object other than Object.prototype as prototype, one can use Object.create:

var a = {};
var b = Object.create(a);
Object.getPrototypeOf(b) === a; // true

title: Prototypes (2)

Now we know what prototypes are, but not what they do or which problem they solve.

What does a prototype do?

Prototypes come in play when we are accessing the property of an object.

Whenver an object property is accessed, the object and its prototype chain are traversed until the property is found. If the end of the prototype chain is reached without finding the property, undefined is returned.

Consider the following structure:

:::ascii

┌───────────────────────┐
│           a           │
├───────────────┬───────┤
│ name          │ "Tom" │
├───────────────┼───────┤
│ [[Prototype]] │   ◆───┼───┐
└───────────────┴───────┘   │
                            ▼
                ┌───────────────────────┐
                │           b           │
                ├───────────────┬───────┤
                │ name          │ "Joe" │
                ├───────────────┼───────┤
                │ age           │   42  │
                ├───────────────┼───────┤
                │ [[Prototype]] │   ◆───┼───┐
                └───────────────┴───────┘   │
                                            ▼
                                ┌───────────────────────┐
                                │           c           │
                                ├───────────────┬───────┤
                                │ height        │  180  │
                                ├───────────────┼───────┤
                                │ [[Prototype]] │  null │
                                └───────────────┴───────┘

:::

These are the results for accessing different properties on A:

a.name; // Tom        `a` itself has this property, it shadows `b.name`
a.age; // 42         `a`'s prototype has this property
a.height; // 180        `a`'s prototype's prototype has this property
a.eyeColor; // undefined  this property doesn't exist

This is also the reason why we can access .toString() on almost every object: It is defined in Object.prototype, which sits at the end of every prototype chain.

var user = { name: 'Tom' };
user.toString();
// "[object Object]"

Note: Assignments to properties will (almost) always create or update a property on object itself, even if a property with the same name already exists in the prototype chain. The property in the prototype chain is then shadowed, similar to variable shadowing in scopes.


title: 'Built-in objects: Arrays and functions'

Arrays

Arrays are objects, which treat properties with numeric keys (i.e. 0, 1, 2, ...) in a special way. For all purposes, they behave like arrays in other languages.

JavaScript has a special syntax for creating arrays, [value, value, ...]:

var arr = [1, 2];

If you run console.dir([1, 2]) in your browser's console, you can inspect the structure of the array object in more detail.

Unlike "plain" objects, array objects have Array.prototype as prototype, which provides all the array methods, such as .push, .map, etc.

:::ascii

┌──────────┐       [[Prototype]]        ┌──────────────────┐
│  obj {}  │───────────────────────────▶│ Object.prototype │
└──────────┘                            └──────────────────┘
                                                  ▲
                                                  │
                                            [[Prototype]]
                                                  │
┌──────────┐ [[Prototype]]  ┌─────────────────┐   │
│  arr []  │───────────────▶│ Array.prototype │───┘
└──────────┘                └─────────────────┘

:::


Functions

Functions are the only kind of objects that are callable, and JavaScript also has a special syntax for defining them:

function foo() {
    console.log("I'm a function");
}

There are other ways to create functions, which will be explained later.

The most important implication of functions being objects is that "work" just like any other value. Functions can be passed to functions and returned from functions, allowing to creation of higher-order functions.

Similar to arrays, function objects also have a dedicated prototype, Function.prototype:

:::ascii

┌──────────┐         [[Prototype]]          ┌──────────────────┐
│  obj {}  │───────────────────────────────▶│ Object.prototype │
└──────────┘                                └──────────────────┘
                                                ▲         ▲
                                                │         │
                                          [[Prototype]]   │
┌──────────┐ [[Prototype]]  ┌─────────────────┐ │         │
│  arr []  │───────────────▶│ Array.prototype │─┘         │
└──────────┘                └─────────────────┘     [[Prototype]]
                                                          │
                                                          │
┌──────────────────┐ [[Prototype]]  ┌──────────────────┐  │
│func function(){} │───────────────▶│Function.prototype│──┘
└──────────────────┘                └──────────────────┘

:::


title: Control structures

JavaScript provides the same control structures known from other C-like languages:

  • if (...) { ... } else if (...) { ... } else { ... }

  • while (...) { ... } and do { ... } while (...)

  • for (...; ...; ...) { ... }

  • switch (...) { case ...: ... }

Additionally, JavaScript provides the for...in loop to iterate over properties of objects:

for (var prop in obj) {
    console.log(prop, obj[prop]);
}

prop is a variable containing the property name. You can use bracket notation to access the property values.

ES2015

ES2015 introduces [for/of][forof] statements for iterating over [iterables][]:

var arr = [1, 2, 3];
for (var v of arr) {
    console.log(v);
}
// 1
// 2
// 3

title: Demo layout_data: description: Run this code and look at the output. Do you notice anything unexpected? If yes, why do you think this is the case?

var obj = {foo: 0, bar: 1, 42: 2};

for (var prop in obj) { log('property: ' + prop, 'value: ' + obj[prop]); }


title: Exercise layout_data: description: | Log two value: an object which has a property foo and a value "bar", and an array with the values 1, 2 and 42. assertion: | assert( output.some(function(x) { return JSON.stringify(x) === JSON.stringify({foo: 'bar'}); }), 'Your log must contain an object with property "foo" and value "bar". Hint: {key: value}.' );

    assert(
      output.some(function(x) {
        return JSON.stringify(x) === JSON.stringify([1, 2, 42]);
      }),
      'Your log must contain an array with values 1, 2 and 42. Hint: `[value, ...]`.'
    );


title: Resources


title: Function definitions

There are two syntactic constructs to create functions: function declaration and function expressions.

Function declarations start with the function keyword followed by a name, the parameter list and the function body:

function foo(a, b, c) {
    // do something
}

Function expressions have the same structure, but their name is optional:

var foo = function (a, b, c) {
    // do something
};

Note: Since functions are objects, they can be treated like any other value. They can be assigned to variables, passed to other functions and returned from functions. The code above is just an assignment expression with a function as value.

All function objects created either way behave exactly the same. Whether the parser treats a function definition as declaration or expression depends on where the definition is placed. If it is an expression context, it is interpreted as an expression, otherwise as a declaration. That's why

function () { }

generates an error (function declaration without name), but

(function () {});

does not, because the grouping operator ((...)) can only contain expressions.


title: Function Calls

Like other C-like languages, functions are called by putting () after the function reference:

myFunction();

Unlike other languages, functions can be called with any number of arguments, no matter how many formal parameters they have:

function myFunction(foo, bar) {
    console.log(foo, bar);
}

myFunction(); // undefined undefined
myFunction(1); // 1 undefined
myFunction(1, 2); // 1 2
myFunction(1, 2, 3); // 1 2

Each function has access to the special arguments variable, which is an array-like value. This allows you to access all the arguments passed to a function, even if there are more than formal parameters:

function myFunction(foo, bar) {
    console.log(foo, bar, arguments);
}

myFunction(); // undefined undefined []
myFunction(1); // 1 undefined [1]
myFunction(1, 2); // 1 2 [1, 2]
myFunction(1, 2, 3); // 1 2 [1, 2, 3]

title: Insert item inside an Array

tip-number: 00 tip-username: loverajoel tip-username-profile: https://github.com/loverajoel tip-tldr: Inserting an item into an existing array is a daily common task. You can add elements to the end of an array using push, to the beginning using unshift, or to the middle using splice. tip-writer-support: https://www.coinbase.com/loverajoel

  • /en/insert-item-inside-an-array/

Inserting an item into an existing array

Inserting an item into an existing array is a daily common task. You can add elements to the end of an array using push, to the beginning using unshift, or to the middle using splice.

Those are known methods, but it doesn't mean there isn't a more performant way. Here we go:

Adding an element at the end

Adding an element at the end of the array is easy with push(), but it can be done in different ways.

var arr = [1, 2, 3, 4, 5];
var arr2 = [];

arr.push(6);
arr[arr.length] = 6;
arr2 = arr.concat([6]);

Both first methods modify the original array. Don't believe me? Check the jsperf

Performance on mobile :

Android (v4.2.2)

  1. arr.push(6); and arr[arr.length] = 6; have the same performance // 3 319 694 ops/sec
  2. arr2 = arr.concat([6]); 50.61 % slower than the other two methods

Chrome Mobile (v33.0.0)

  1. arr[arr.length] = 6; // 6 125 975 ops/sec
  2. arr.push(6); 66.74 % slower
  3. arr2 = arr.concat([6]); 87.63 % slower

Safari Mobile (v9)

  1. arr[arr.length] = 6; // 7 452 898 ops/sec
  2. arr.push(6); 40.19 % slower
  3. arr2 = arr.concat([6]); 49.78 % slower
Final victor

1. arr[arr.length] = 6; // with an average of 5 632 856 ops/sec
2. arr.push(6); // 35.64 % slower
3. arr2 = arr.concat([6]); // 62.67 % slower

Performance on desktop

Chrome (v48.0.2564)

  1. arr[arr.length] = 6; // 21 602 722 ops/sec
  2. arr.push(6); 61.94 % slower
  3. arr2 = arr.concat([6]); 87.45 % slower

Firefox (v44)

  1. arr.push(6); // 56 032 805 ops/sec
  2. arr[arr.length] = 6; 0.52 % slower
  3. arr2 = arr.concat([6]); 87.36 % slower

IE (v11)

  1. arr[arr.length] = 6; // 67 197 046 ops/sec
  2. arr.push(6); 39.61 % slower
  3. arr2 = arr.concat([6]); 93.41 % slower

Opera (v35.0.2066.68)

  1. arr[arr.length] = 6; // 30 775 071 ops/sec
  2. arr.push(6); 71.60 % slower
  3. arr2 = arr.concat([6]); 83.70 % slower

Safari (v9.0.3)

  1. arr.push(6); // 42 670 978 ops/sec
  2. arr[arr.length] = 6; 0.80 % slower
  3. arr2 = arr.concat([6]); 76.07 % slower
Final victor

1. arr[arr.length] = 6; // with an average of 42 345 449 ops/sec
2. arr.push(6); // 34.66 % slower
3. arr2 = arr.concat([6]); // 85.79 % slower

Add an element at the beginning

Now if we are trying to add an item to the beginning of the array:

var arr = [1, 2, 3, 4, 5];

arr.unshift(0);
[0].concat(arr);

Here is a little more detail: unshift edits the original array; concat returns a new array. jsperf

Performance on mobile :

Android (v4.2.2)

  1. [0].concat(arr); // 1 808 717 ops/sec
  2. arr.unshift(0); 97.85 % slower

Chrome Mobile (v33.0.0)

  1. [0].concat(arr); // 1 269 498 ops/sec
  2. arr.unshift(0); 99.86 % slower

Safari Mobile (v9)

  1. arr.unshift(0); // 3 250 184 ops/sec
  2. [0].concat(arr); 33.67 % slower
Final victor

1. [0].concat(arr); // with an average of 4 972 622 ops/sec
2. arr.unshift(0); // 64.70 % slower

Performance on desktop

Chrome (v48.0.2564)

  1. [0].concat(arr); // 2 656 685 ops/sec
  2. arr.unshift(0); 96.77 % slower

Firefox (v44)

  1. [0].concat(arr); // 8 039 759 ops/sec
  2. arr.unshift(0); 99.72 % slower

IE (v11)

  1. [0].concat(arr); // 3 604 226 ops/sec
  2. arr.unshift(0); 98.31 % slower

Opera (v35.0.2066.68)

  1. [0].concat(arr); // 4 102 128 ops/sec
  2. arr.unshift(0); 97.44 % slower

Safari (v9.0.3)

  1. arr.unshift(0); // 12 356 477 ops/sec
  2. [0].concat(arr); 15.17 % slower
Final victor

1. [0].concat(arr); // with an average of 6 032 573 ops/sec
2. arr.unshift(0); // 78.65 % slower

Add an element in the middle

Adding items in the middle of an array is easy with splice, and it's the most performant way to do it.

var items = ['one', 'two', 'three', 'four'];
items.splice(items.length / 2, 0, 'hello');

I tried to run these tests in various Browsers and OS and the results were similar. I hope these tips will be useful for you and encourage to perform your own tests!

title: Improve Nested Conditionals tip-number: 03 tip-username: AlbertoFuente tip-username-profile: https://github.com/AlbertoFuente tip-tldr: How can we improve and make a more efficient nested if statement in javascript?

  • /en/improve-nested-conditionals/

How can we improve and make a more efficient nested if statement in javascript?

if (color) {
    if (color === 'black') {
        printBlackBackground();
    } else if (color === 'red') {
        printRedBackground();
    } else if (color === 'blue') {
        printBlueBackground();
    } else if (color === 'green') {
        printGreenBackground();
    } else {
        printYellowBackground();
    }
}

One way to improve the nested if statement would be using the switch statement. Although it is less verbose and is more ordered, it's not recommended to use it because it's so difficult to debug errors. Here's why.

switch (color) {
    case 'black':
        printBlackBackground();
        break;
    case 'red':
        printRedBackground();
        break;
    case 'blue':
        printBlueBackground();
        break;
    case 'green':
        printGreenBackground();
        break;
    default:
        printYellowBackground();
}

But what if we have a conditional with several checks in each statement? In this case, if we want it less verbose and more ordered, we can use the conditional switch. If we pass true as a parameter to the switch statement, it allows us to put a conditional in each case.

switch (true) {
    case typeof color === 'string' && color === 'black':
        printBlackBackground();
        break;
    case typeof color === 'string' && color === 'red':
        printRedBackground();
        break;
    case typeof color === 'string' && color === 'blue':
        printBlueBackground();
        break;
    case typeof color === 'string' && color === 'green':
        printGreenBackground();
        break;
    case typeof color === 'string' && color === 'yellow':
        printYellowBackground();
        break;
}

If refactoring is an option, we can try to simplify the functions themselves. For example instead of having a function for each background color we could have an function that takes the color as an argument.

function printBackground(color) {
    if (!color || typeof color !== 'string') {
        return; // Invalid color, return immediately
    }
}

But if refactoring is not an option, we must always avoid having several checks in every condition and avoid using switch as much as possible. We also must take into account that the most efficient way to do this is through an object.

var colorObj = {
    black: printBlackBackground,
    red: printRedBackground,
    blue: printBlueBackground,
    green: printGreenBackground,
    yellow: printYellowBackground
};

if (color in colorObj) {
    colorObj[color]();
}

Here you can find more information about this.

title: Sorting strings with accented characters tip-number: 04 tip-username: loverajoel tip-username-profile: https://github.com/loverajoel tip-tldr: Javascript has a native method sort that allows sorting arrays. Doing a simple array.sort() will treat each array entry as a string and sort it alphabetically. But when you try order an array of non ASCII characters you will obtain a strange result. tip-writer-support: https://www.coinbase.com/loverajoel

  • /en/sorting-strings-with-accented-characters/

Javascript has a native method sort that allows sorting arrays. Doing a simple array.sort() will treat each array entry as a string and sort it alphabetically. Also you can provide your own custom sorting function.

['Shanghai', 'New York', 'Mumbai', 'Buenos Aires'].sort();
// ["Buenos Aires", "Mumbai", "New York", "Shanghai"]

But when you try order an array of non ASCII characters like this ['é', 'a', 'ú', 'c'], you will obtain a strange result ['c', 'e', 'á', 'ú']. That happens because sort works only with the English language.

See the next example:

// Spanish
['único', 'árbol', 'cosas', 'fútbol'].sort();
// ["cosas", "fútbol", "árbol", "único"] // bad order

// German
['Woche', 'wöchentlich', 'wäre', 'Wann'].sort();
// ["Wann", "Woche", "wäre", "wöchentlich"] // bad order

Fortunately, there are two ways to overcome this behavior localeCompare and Intl.Collator provided by ECMAScript Internationalization API.

Both methods have their own custom parameters in order to configure it to work adequately.

Using localeCompare()

['único', 'árbol', 'cosas', 'fútbol'].sort(function (a, b) {
    return a.localeCompare(b);
});
// ["árbol", "cosas", "fútbol", "único"]

['Woche', 'wöchentlich', 'wäre', 'Wann'].sort(function (a, b) {
    return a.localeCompare(b);
});
// ["Wann", "wäre", "Woche", "wöchentlich"]

Using Intl.Collator()

['único', 'árbol', 'cosas', 'fútbol'].sort(Intl.Collator().compare);
// ["árbol", "cosas", "fútbol", "único"]

['Woche', 'wöchentlich', 'wäre', 'Wann'].sort(Intl.Collator().compare);
// ["Wann", "wäre", "Woche", "wöchentlich"]
  • For each method you can customize the location.
  • According to Firefox Intl.Collator is faster when comparing large numbers of strings.

So when you are working with arrays of strings in a language other than English, remember to use this method to avoid unexpected sorting.

title: Differences between undefined and null tip-number: 05 tip-username: loverajoel tip-username-profile: https://github.com/loverajoel tip-tldr: Understanding the differences between undefined and null. tip-writer-support: https://www.coinbase.com/loverajoel

  • /en/differences-between-undefined-and-null/

  • undefined means a variable has not been declared, or has been declared but has not yet been assigned a value

  • null is an assignment value that means "no value"

  • Javascript sets unassigned variables with a default value of undefined

  • Javascript never sets a value to null. It is used by programmers to indicate that a var has no value.

  • undefined is not valid in JSON while null is

  • undefined typeof is undefined

  • null typeof is an object. Why?

  • Both are primitives

  • Both are falsy (Boolean(undefined) // false, Boolean(null) // false)

  • You can know if a variable is undefined

    typeof variable === 'undefined';
- You can check if a variable is [null](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null)

  ```javascript
  variable === null
  • The equality operator considers them equal, but the identity doesn't

    null == undefined; // true
    
    null === undefined; // false

title: Writing a single method for arrays and a single element tip-number: 06 tip-username: mattfxyz tip-username-profile: https://twitter.com/mattfxyz tip-tldr: Rather than writing separate methods to handle an array and a single element parameter, write your functions so they can handle both. This is similar to how some of jQuery's functions work (css will modify everything matched by the selector).

  • /en/writing-a-single-method-for-arrays-and-a-single-element/

Rather than writing separate methods to handle an array and a single element parameter, write your functions so they can handle both. This is similar to how some of jQuery's functions work (css will modify everything matched by the selector).

You just have to concat everything into an array first. Array.concat will accept an array or a single element.

function printUpperCase(words) {
    var elements = [].concat(words || []);
    for (var i = 0; i < elements.length; i++) {
        console.log(elements[i].toUpperCase());
    }
}

printUpperCase is now ready to accept a single node or an array of nodes as its parameter. It also avoids the potential TypeError that would be thrown if no parameter was passed.

printUpperCase('cactus');
// => CACTUS
printUpperCase(['cactus', 'bear', 'potato']);
// => CACTUS
//  BEAR
//  POTATO

title: use strict and get lazy tip-number: 07 tip-username: nainslie tip-username-profile: https://twitter.com/nat5an tip-tldr: Strict-mode JavaScript makes it easier for the developer to write "secure" JavaScript.

  • /en/use-strict-and-get-lazy/

Strict-mode JavaScript makes it easier for the developer to write "secure" JavaScript.

By default, JavaScript allows the programmer to be pretty careless, for example, by not requiring us to declare our variables with "var" when we first introduce them. While this may seem like a convenience to the unseasoned developer, it's also the source of many errors when a variable name is misspelled or accidentally referred to out of its scope.

Programmers like to make the computer do the boring stuff for us, and automatically check our work for mistakes. That's what the JavaScript "use strict" directive allows us to do, by turning our mistakes into JavaScript errors.

We add this directive either by adding it at the top of a js file:

// Whole-script strict mode syntax
'use strict';
var v = "Hi!  I'm a strict mode script!";

or inside a function:

function f() {
    // Function-level strict mode syntax
    'use strict';
    function nested() {
        return 'And so am I!';
    }
    return "Hi!  I'm a strict mode function!  " + nested();
}
function f2() {
    return "I'm not strict.";
}

By including this directive in a JavaScript file or function, we will direct the JavaScript engine to execute in strict mode which disables a bunch of behaviors that are usually undesirable in larger JavaScript projects. Among other things, strict mode changes the following behaviors:

  • Variables can only be introduced when they are preceded with "var"
  • Attempting to write to read-only properties generates a noisy error
  • You have to call constructors with the "new" keyword
  • "this" is not implicitly bound to the global object
  • Very limited use of eval() allowed
  • Protects you from using reserved words or future reserved words as variable names

Strict mode is great for new projects, but can be challenging to introduce into older projects that don't already use it in most places. It also can be problematic if your build chain concatenates all your js files into one big file, as this may cause all files to execute in strict mode.

It is not a statement, but a literal expression, ignored by earlier versions of JavaScript. Strict mode is supported in:

  • Internet Explorer from version 10.
  • Firefox from version 4.
  • Chrome from version 13.
  • Safari from version 5.1.
  • Opera from version 12.

See MDN for a fuller description of strict mode.

title: Converting a Node List to an Array tip-number: 08 tip-username: Tevko tip-username-profile: https://twitter.com/tevko tip-tldr: Here's a quick, safe, and reusable way to convert a node list into an array of DOM elements.

  • /en/converting-a-node-list-to-an-array/

The querySelectorAll method returns an array-like object called a node list. These data structures are referred to as "Array-like", because they appear as an array, but can not be used with array methods like map and forEach. Here's a quick, safe, and reusable way to convert a node list into an array of DOM elements:

const nodelist = document.querySelectorAll('div');
const nodelistToArray = Array.apply(null, nodelist);

//later on ..

nodelistToArray.forEach(...);
nodelistToArray.map(...);
nodelistToArray.slice(...);

//etc...

The apply method is used to pass an array of arguments to a function with a given this value. MDN states that apply will take an array-like object, which is exactly what querySelectorAll returns. Since we don't need to specify a value for this in the context of the function, we pass in null or 0. The result is an actual array of DOM elements which contains all of the available array methods.

Alternatively you can use Array.prototype.slice combined with Function.prototype.call or Function.prototype.apply passing the array-like object as the value of this:

const nodelist = document.querySelectorAll('div');
const nodelistToArray = Array.prototype.slice.call(nodelist); // or equivalently Array.prototype.slice.apply(nodelist);

//later on ..

nodelistToArray.forEach(...);
nodelistToArray.map(...);
nodelistToArray.slice(...);

//etc...

Or if you are using ES2015 you can use the spread operator ...

const nodelist = [...document.querySelectorAll('div')]; // returns a real array

//later on ..

nodelist.forEach(...);
nodelist.map(...);
nodelist.slice(...);

//etc...

title: Template Strings tip-number: 09 tip-username: JakeRawr tip-username-profile: https://github.com/JakeRawr tip-tldr: As of ES6, JS now has template strings as an alternative to the classic end quotes strings.

  • /en/template-strings/

As of ES6, JS now has template strings as an alternative to the classic end quotes strings.

Ex: Normal string

var firstName = 'Jake';
var lastName = 'Rawr';
console.log('My name is ' + firstName + ' ' + lastName);
// My name is Jake Rawr

Template String

var firstName = 'Jake';
var lastName = 'Rawr';
console.log(`My name is ${firstName} ${lastName}`);
// My name is Jake Rawr

You can do multi-line strings without \n, perform simple logic (ie 2+3) or even use the ternary operator inside ${} in template strings.

var val1 = 1,
    val2 = 2;
console.log(`${val1} is ${val1 < val2 ? 'less than' : 'greater than'} ${val2}`);
// 1 is less than 2

You are also able to modify the output of template strings using a function; they are called tagged template strings for example usages of tagged template strings.

You may also want to read to understand template strings more.

title: Check if a property is in a Object tip-number: 10 tip-username: loverajoel tip-username-profile: https://www.twitter.com/loverajoel tip-tldr: These are ways to check if a property is present in an object. tip-writer-support: https://www.coinbase.com/loverajoel

  • /en/check-if-a-property-is-in-a-object/

When you have to check if a property is present in an object, you probably are doing something like this:

var myObject = {
  name: '@tips_js'
};

if (myObject.name) { ... }

That's ok, but you have to know that there are two native ways for this kind of thing, the in operator and Object.hasOwnProperty. Every object descended from Object, has both ways available.

See the big Difference

var myObject = {
    name: '@tips_js'
};

myObject.hasOwnProperty('name'); // true
'name' in myObject; // true

myObject.hasOwnProperty('valueOf'); // false, valueOf is inherited from the prototype chain
'valueOf' in myObject; // true

Both differ in the depth at which they check the properties. In other words, hasOwnProperty will only return true if key is available on that object directly. However, the in operator doesn't discriminate between properties created on an object and properties inherited from the prototype chain.

Here's another example:

var myFunc = function () {
    this.name = '@tips_js';
};
myFunc.prototype.age = '10 days';

var user = new myFunc();

user.hasOwnProperty('name'); // true
user.hasOwnProperty('age'); // false, because age is from the prototype chain

Check the live examples here!

I also recommend reading this discussion about common mistakes made when checking a property's existence in objects.

title: Hoisting tip-number: 11 tip-username: squizzleflip tip-username-profile: https://twitter.com/squizzleflip tip-tldr: Understanding hoisting will help you organize your function scope.

Understanding hoisting will help you organize your function scope. Just remember, variable declarations and function definitions are hoisted to the top. Variable definitions are not, even if you declare and define a variable on the same line. Also, a variable declaration lets the system know that the variable exists while definition assigns it a value.

function doTheThing() {
    // ReferenceError: notDeclared is not defined
    console.log(notDeclared);

    // Outputs: undefined
    console.log(definedLater);
    var definedLater;

    definedLater = 'I am defined!';
    // Outputs: 'I am defined!'
    console.log(definedLater);

    // Outputs: undefined
    console.log(definedSimulateneously);
    var definedSimulateneously = 'I am defined!';
    // Outputs: 'I am defined!'
    console.log(definedSimulateneously);

    // Outputs: 'I did it!'
    doSomethingElse();

    function doSomethingElse() {
        console.log('I did it!');
    }

    // TypeError: undefined is not a function
    functionVar();

    var functionVar = function () {
        console.log('I did it!');
    };
}

To make things easier to read, declare all of your variables at the top of your function scope so it is clear which scope the variables are coming from. Define your variables before you need to use them. Define your functions at the bottom of your scope to keep them out of your way.

title: Pseudomandatory parameters in ES6 functions tip-number: 12 tip-username: Avraam Mavridis tip-username-profile: https://github.com/AvraamMavridis tip-tldr: In many programming languages the parameters of a function are by default mandatory and the developer has to explicitly define that a parameter is optional.

  • /en/pseudomandatory-parameters-in-es6-functions/

In many programming languages the parameters of a function are by default mandatory and the developer has to explicitly define that a parameter is optional. In Javascript, every parameter is optional, but we can enforce this behavior without messing with the actual body of a function, taking advantage of [es6's default values for parameters] (http://exploringjs.com/es6/ch_parameter-handling.html#sec_parameter-default-values) feature.

const _err = function (message) {
    throw new Error(message);
};

const getSum = (a = _err('a is not defined'), b = _err('b is not defined')) => a + b;

getSum(10); // throws Error, b is not defined
getSum(undefined, 10); // throws Error, a is not defined

_err is a function that immediately throws an Error. If no value is passed for one of the parameters, the default value is going to be used, _err will be called and an Error will be thrown. You can see more examples for the default parameters feature on Mozilla's Developer Network

title: Tip to measure performance of a javascript block tip-number: 13 tip-username: manmadareddy tip-username-profile: https://twitter.com/manmadareddy tip-tldr: For quickly measuring performance of a javascript block, we can use the console functions like console.time(label) and console.timeEnd(label)

  • /en/tip-to-measure-performance-of-a-javascript-block/

For quickly measuring performance of a javascript block, we can use the console functions like console.time(label) and console.timeEnd(label)

console.time('Array initialize');
var arr = new Array(100),
    len = arr.length,
    i;

for (i = 0; i < len; i++) {
    arr[i] = new Object();
}
console.timeEnd('Array initialize'); // Outputs: Array initialize: 0.711ms

More info: Console object, Javascript benchmarking

Demo: jsfiddle - codepen (outputs in browser console)

Note: As Mozilla suggested don't use this for production sites, use it for development purposes only.

title: Fat Arrow Functions tip-number: 14 tip-username: pklinger tip-username-profile: https://github.com/pklinger/ tip-tldr: Introduced as a new feature in ES6, fat arrow functions may come as a handy tool to write more code in fewer lines

  • /en/fat-arrow-functions/

Introduced as a new feature in ES6, fat arrow functions may come as a handy tool to write more code in fewer lines. The name comes from its syntax, =>, which is a 'fat arrow', as compared to a thin arrow ->. Some programmers might already know this type of function from different languages such as Haskell, as 'lambda expressions', or as 'anonymous functions'. It is called anonymous, as these arrow functions do not have a descriptive function name.

What are the benefits?

  • Syntax: fewer LOC; no more typing function keyword over and over again
  • Semantics: capturing the keyword this from the surrounding context

Simple syntax example

Have a look at these two code snippets, which do the exact same job, and you will quickly understand what fat arrow functions do:

// general syntax for fat arrow functions
param => expression

// may also be written with parentheses
// parentheses are required on multiple params
(param1 [, param2]) => expression


// using functions
var arr = [5,3,2,9,1];
var arrFunc = arr.map(function(x) {
  return x * x;
});
console.log(arr)

// using fat arrow
var arr = [5,3,2,9,1];
var arrFunc = arr.map((x) => x*x);
console.log(arr)

As you can see, the fat arrow function in this case can save you time typing out the parentheses as well as the function and return keywords. I would advise you to always write parentheses around the parameter inputs, as the parentheses will be needed for multiple input parameters, such as in (x,y) => x+y. It is just a way to cope with forgetting them in different use cases. But the code above would also work like this: x => x*x. So far, these are only syntactical improvements, which lead to fewer LOC and better readability.

Lexically binding this

There is another good reason to use fat arrow functions. There is the issue with the context of this. With arrow functions, you don't need to worry about .bind(this) or setting that = this anymore, as fat arrow functions pick the context of this from the lexical surrounding. Have a look at the next [example] (https://jsfiddle.net/pklinger/rw94oc11/):

// globally defined this.i
this.i = 100;

var counterA = new CounterA();
var counterB = new CounterB();
var counterC = new CounterC();
var counterD = new CounterD();

// bad example
function CounterA() {
    // CounterA's `this` instance (!! gets ignored here)
    this.i = 0;
    setInterval(function () {
        // `this` refers to global object, not to CounterA's `this`
        // therefore starts counting with 100, not with 0 (local this.i)
        this.i++;
        document.getElementById('counterA').innerHTML = this.i;
    }, 500);
}

// manually binding that = this
function CounterB() {
    this.i = 0;
    var that = this;
    setInterval(function () {
        that.i++;
        document.getElementById('counterB').innerHTML = that.i;
    }, 500);
}

// using .bind(this)
function CounterC() {
    this.i = 0;
    setInterval(
        function () {
            this.i++;
            document.getElementById('counterC').innerHTML = this.i;
        }.bind(this),
        500
    );
}

// fat arrow function
function CounterD() {
    this.i = 0;
    setInterval(() => {
        this.i++;
        document.getElementById('counterD').innerHTML = this.i;
    }, 500);
}

Further information about fat arrow functions may be found at MDN (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions). To see different syntax options visit [this site] (http://jsrocks.org/2014/10/arrow-functions-and-their-scope/).

title: Even simpler way of using indexOf as a contains clause tip-number: 15 tip-username: jhogoforbroke tip-username-profile: https://twitter.com/jhogoforbroke tip-tldr: JavaScript by default does not have a contains method. And for checking existence of a substring in a string or an item in an array you may do this.

  • /en/even-simpler-way-of-using-indexof-as-a-contains-clause/

JavaScript by default does not have a contains method. And for checking existence of a substring in a string or an item in an array you may do this:

var someText = 'javascript rules';
if (someText.indexOf('javascript') !== -1) {
}

// or
if (someText.indexOf('javascript') >= 0) {
}

But let's look at these Expressjs code snippets.

examples/mvc/lib/boot.js

for (var key in obj) {
  // "reserved" exports
  if (~['name', 'prefix', 'engine', 'before'].indexOf(key)) continue;

lib/utils.js

exports.normalizeType = function (type) {
    return ~type.indexOf('/') ? acceptParams(type) : { value: mime.lookup(type), params: {} };
};

examples/web-service/index.js

// key is invalid
if (!~apiKeys.indexOf(key)) return next(error(401, 'invalid api key'));

The gotcha is the bitwise operator ~, "Bitwise operators perform their operations on binary representations, but they return standard JavaScript numerical values."

It transforms -1 into 0, and 0 evaluates to false in JavaScript:

var someText = 'text';
!!~someText.indexOf('tex'); // someText contains "tex" - true
!~someText.indexOf('tex'); // someText NOT contains "tex" - false
~someText.indexOf('asd'); // someText doesn't contain "asd" - false
~someText.indexOf('ext'); // someText contains "ext" - true

String.prototype.includes()

ES6 introduced the includes() method and you can use it to determine whether or not a string includes another string:

'something'.includes('thing'); // true

With ECMAScript 2016 (ES7) it is even possible to use these techniques with Arrays:

!!~[1, 2, 3].indexOf(1); // true
[1, 2, 3].includes(1); // true

Unfortunately, it is only supported in Chrome, Firefox, Safari 9 or above and Edge; not IE11 or lower. It's better used in controlled environments.

title: Passing arguments to callback functions tip-number: 16 tip-username: minhazav tip-username-profile: https://twitter.com/minhazav tip-tldr: By default you cannot pass arguments to a callback function, but you can take advantage of the closure scope in Javascript to pass arguments to callback functions.

  • /en/passing-arguments-to-callback-functions/

By default you cannot pass arguments to a callback function. For example:

function callback() {
    console.log('Hi human');
}

document.getElementById('someelem').addEventListener('click', callback);

You can take advantage of the closure scope in Javascript to pass arguments to callback functions. Check this example:

function callback(a, b) {
    return function () {
        console.log('sum = ', a + b);
    };
}

var x = 1,
    y = 2;
document.getElementById('someelem').addEventListener('click', callback(x, y));

What are closures?

Closures are functions that refer to independent (free) variables. In other words, the function defined in the closure 'remembers' the environment in which it was created. Check MDN Documentation to learn more.

So this way the arguments x and y are in scope of the callback function when it is called.

Another method to do this is using the bind method. For example:

var alertText = function (text) {
    alert(text);
};

document.getElementById('someelem').addEventListener('click', alertText.bind(this, 'hello'));

There is a very slight difference in performance of both methods, checkout jsperf.

title: Node.js - Run a module if it is not required tip-number: 17 tip-username: odsdq tip-username-profile: https://twitter.com/odsdq tip-tldr: In node, you can tell your program to do two different things depending on whether the code is run from require('./something.js') or node something.js. This is useful if you want to interact with one of your modules independently.

  • /en/nodejs-run-a-module-if-it-is-not-required/

In node, you can tell your program to do two different things depending on whether the code is run from require('./something.js') or node something.js. This is useful if you want to interact with one of your modules independently.

if (!module.parent) {
    // ran with `node something.js`
    app.listen(8088, function () {
        console.log('app listening on port 8088');
    });
} else {
    // used with `require('/.something.js')`
    module.exports = app;
}

See the documentation for modules for more info.

title: Truncating the fast (but risky) way tip-number: 18 tip-username: pklinger tip-username-profile: https://github.com/pklinger tip-tldr: .~~X is usually a faster Math.trunc(X), but can also make your code do nasty things.

  • /en/rounding-the-fast-way/

This tip is about performance...with a hidden price tag.

Have you ever come across the double tilde ~~ operator? It's also often called the "double bitwise NOT" operator. You can often use it as a faster substitute for Math.trunc(). Why is that?

One bitwise shift ~ first truncates input to 32 bits, then transforms it into -(input+1). The double bitwise shift therefore transforms the input into -(-(input + 1)+1) making it a great tool to round towards zero. For numeric input, it therefore mimics Math.trunc(). On failure, 0 is returned, which might come in handy sometimes instead of Math.trunc(), which returns NaN on failure.

// single ~
console.log(~1337); // -1338

// numeric input
console.log(~~47.11); // -> 47
console.log(~~1.9999); // -> 1
console.log(~~3); // -> 3

However, while ~~ is probably a better performer, experienced programmers often stick with Math.trunc() instead. To understand why, here's a clinical view on this operator.

INDICATIONS

When every CPU cycle counts

~~ is probably faster than Math.trunc() across the board, though you should test that assumption on whichever platforms matter to you. Also, you'd generally have to perform millions of such operations to have any visible impact at run time.

When code clarity is not a concern

If you're trying to confuse others, or get maximum utility from your minifier/uglifier, this is a relatively cheap way to do it.

CONTRAINDICATIONS

When your code needs to be maintained

Code clarity is of great importance in the long term, whether you work in a team, contribute to public code repos, or fly solo. As the oft-quoted saying goes:

Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live.

For a solo programmer, that psychopath is inevitably "you in six months".

When you forget that ~~ always rounds to zero

Newbie programmers may fixate on the cleverness of ~~, forgetting the significance of "just drop the fractional portion of this number". This can easily lead to fencepost errors (a.k.a. "off-by-one") when transforming floats to array indices or related ordinal values, where a different kind of fractional rounding may actually be called for. (Lack of code clarity usually contributes to this problem.)

For instance, if you're counting numbers on a "nearest integer" basis, you should use Math.round() instead of ~~, but programmer laziness and the impact of 10 whole characters saved per use on human fingers often triumph over cold logic, leading to incorrect results.

In contrast, the very names of the Math.xyz() functions clearly communicate their effect, reducing the probability of accidental errors.

When dealing with large-magnitude numbers

Because ~ first does a 32-bit conversion, ~~ results in bogus values around ±2.15 billion. If you don't properly range-check your input, a user could trigger unexpected behavior when the transformed value ends up being a great distance from the original:

a = 2147483647.123; // maximum positive 32-bit integer, plus a bit more
console.log(~~a); // ->  2147483647     (ok)
a += 10000; // ->  2147493647.123 (ok)
console.log(~~a); // -> -2147483648     (huh?)

One particularly vulnerable area involves dealing with Unix epoch timestamps (measured in seconds from 1 Jan 1970 00:00:00 UTC). A quick way to get such values is:

epoch_int = ~~(+new Date() / 1000); // Date() epochs in milliseconds, so we scale accordingly

However, when dealing with timestamps after 19 Jan 2038 03:14:07 UTC (sometimes called the Y2038 limit), this breaks horribly:

// epoch timestamp for 1 Jan 2040 00:00:00.123 UTC
epoch = +new Date('2040-01-01') / 1000 + 0.123; // ->  2208988800.123

// back to the future!
epoch_int = ~~epoch; // -> -2085978496
console.log(new Date(epoch_int * 1000)); // ->  Wed Nov 25 1903 17:31:44 UTC

// that was fun, now let's get real
epoch_flr = Math.floor(epoch); // ->  2208988800
console.log(new Date(epoch_flr * 1000)); // ->  Sun Jan 01 2040 00:00:00 UTC
When the original input wasn't sanitized

Because ~~ transforms every non-number into 0:

console.log(~~[]); // -> 0
console.log(~~NaN); // -> 0
console.log(~~null); // -> 0

some programmers treat it as alternative to proper input validation. However, this can lead to strange logic bugs down the line, since you're no longer distinguishing between invalid inputs and actual 0 values. This is therefore not a recommended practice.

When so many people think ~~X == Math.floor(X)

Most people who write about "double bitwise NOT" incorrectly equate it with Math.floor() for some reason. If you can't write about it accurately, odds are good you'll eventually misuse it.

Others are more careful to mention Math.floor() for positive inputs and Math.ceil() for negative ones, but that forces you to stop and think about the values you're dealing with. This defeats the purpose of ~~ as a handy no-gotchas shortcut.

DOSAGE

Avoid where possible. Use sparingly otherwise.

ADMINISTRATION

  1. Apply cautiously.
  2. Sanitize values before applying.
  3. Carefully document relevant assumptions about the values being transformed.
  4. Review code to deal with, at minimum:
    • logic bugs where invalid inputs are instead passed to other code modules as valid 0 values
    • range errors on transformed inputs
    • fencepost errors due to incorrect rounding direction

title: Safe string concatenation tip-number: 19 tip-username: gogainda tip-username-profile: https://twitter.com/gogainda tip-tldr: Suppose you have a couple of variables with unknown types and you want to concatenate them in a string. To be sure that the arithmetical operation is not be applied during concatenation, use concat

  • /en/safe-string-concatenation/

Suppose you have a couple of variables with unknown types and you want to concatenate them in a string. To be sure that the arithmetical operation is not be applied during concatenation, use concat:

var one = 1;
var two = 2;
var three = '3';

var result = ''.concat(one, two, three); //"123"

This way of concatenting does exactly what you'd expect. In contrast, concatenation with pluses might lead to unexpected results:

var one = 1;
var two = 2;
var three = '3';

var result = one + two + three; //"33" instead of "123"

Speaking about performance, compared to the join type of concatenation, the speed of concat is pretty much the same.

You can read more about the concat function on MDN page.

title: Return objects to enable chaining of functions tip-number: 20 tip-username: WakeskaterX tip-username-profile: https://twitter.com/WakeStudio tip-tldr: When creating functions on an object in Object Oriented Javascript, returning the object in the function will enable you to chain functions together.

  • /en/return-objects-to-enable-chaining-of-functions/

When creating functions on an object in Object Oriented Javascript, returning the object in the function will enable you to chain functions together.

function Person(name) {
    this.name = name;

    this.sayName = function () {
        console.log('Hello my name is: ', this.name);
        return this;
    };

    this.changeName = function (name) {
        this.name = name;
        return this;
    };
}

var person = new Person('John');
person.sayName().changeName('Timmy').sayName();

title: Shuffle an Array tip-number: 21 tip-username: 0xmtn tip-username-profile: https://github.com/0xmtn/ tip-tldr: Fisher-Yates Shuffling it's an algorithm to shuffle an array.

  • /en/shuffle-an-array/

This snippet here uses Fisher-Yates Shuffling Algorithm to shuffle a given array.

function shuffle(arr) {
    var i, j, temp;
    for (i = arr.length - 1; i > 0; i--) {
        j = Math.floor(Math.random() * (i + 1));
        temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
    return arr;
}

An example:

var a = [1, 2, 3, 4, 5, 6, 7, 8];
var b = shuffle(a);
console.log(b);
// [2, 7, 8, 6, 5, 3, 1, 4]

title: Two ways to empty an array tip-number: 22 tip-username: microlv tip-username-profile: https://github.com/microlv tip-tldr: In JavaScript when you want to empty an array, there are a lot ways, but this is the most performant.

  • /en/two-ways-to-empty-an-array/

You define an array and want to empty its contents. Usually, you would do it like this:

// define Array
var list = [1, 2, 3, 4];
function empty() {
    //empty your array
    list = [];
}
empty();

But there is another way to empty an array that is more performant.

You should use code like this:

var list = [1, 2, 3, 4];
function empty() {
    //empty your array
    list.length = 0;
}
empty();
  • list = [] assigns a reference to a new array to a variable, while any other references are unaffected. which means that references to the contents of the previous array are still kept in memory, leading to memory leaks.

  • list.length = 0 deletes everything in the array, which does hit other references.

In other words, if you have two references to the same array (a = [1,2,3]; a2 = a;), and you delete the array's contents using list.length = 0, both references (a and a2) will now point to the same empty array. (So don't use this technique if you don't want a2 to hold an empty array!)

Think about what this will output:

var foo = [1, 2, 3];
var bar = [1, 2, 3];
var foo2 = foo;
var bar2 = bar;
foo = [];
bar.length = 0;
console.log(foo, bar, foo2, bar2);

// [] [] [1, 2, 3] []

Stackoverflow more detail: difference-between-array-length-0-and-array

title: Converting to number fast way tip-number: 23 tip-username: sonnyt tip-username-profile: http://twitter.com/sonnyt tip-tldr: Converting strings to numbers is extremely common. The easiest and fastest way to achieve that would be using the + operator.

  • /en/converting-to-number-fast-way/

Converting strings to numbers is extremely common. The easiest and fastest (jsPerf) way to achieve that would be using the + (plus) operator.

var one = '1';

var numberOne = +one; // Number 1

You can also use the - (minus) operator which type-converts the value into number but also negates it.

var one = '1';

var negativeNumberOne = -one; // Number -1

title: Use === instead of == tip-number: 24 tip-username: bhaskarmelkani tip-username-profile: https://www.twitter.com/bhaskarmelkani tip-tldr: The == (or !=) operator performs an automatic type conversion if needed. The === (or !==) operator will not perform any conversion. It compares the value and the type, which could be considered faster (jsPref) than ==.

  • /en/use*===_instead_of*==/

The == (or !=) operator performs an automatic type conversion if needed. The === (or !==) operator will not perform any conversion. It compares the value and the type, which could be considered faster (jsPref) than ==.

[10] ==  10      // is true
[10] === 10      // is false

'10' ==  10      // is true
'10' === 10      // is false

 []  ==  0       // is true
 []  === 0       // is false

 ''  ==  false   // is true but true == "a" is false
 ''  === false   // is false

title: Using immediately invoked function expression tip-number: 25 tip-username: rishantagarwal tip-username-profile: https://github.com/rishantagarwal tip-tldr: Called as "Iffy" ( IIFE - immediately invoked function expression) is an anonymous function expression that is immediately invoked and has some important uses in Javascript.

  • /en/Using-immediately-invoked-function-expression/

Called as "Iffy" ( IIFE - immediately invoked function expression) is an anonymous function expression that is immediately invoked and has some important uses in Javascript.

(function () {
    // Do something​
})();

It is an anonymous function expression that is immediately invoked, and it has some particularly important uses in JavaScript.

The pair of parenthesis surrounding the anonymous function turns the anonymous function into a function expression or variable expression. So instead of a simple anonymous function in the global scope, or wherever it was defined, we now have an unnamed function expression.

Similarly, we can even create a named, immediately invoked function expression:

(someNamedFunction = function(msg) {
	console.log(msg || "Nothing for today !!")
	}) (); // Output --> Nothing for today !!​someNamedFunction("Javascript rocks !!"); // Output --> Javascript rocks !!
someNamedFunction(); // Output --> Nothing for today !!​

For more details, check the following URL's -

  1. Link 1
  2. Link 2

Performance: jsPerf

title: Filtering and Sorting a List of Strings tip-number: 26 tip-username: davegomez tip-username-profile: https://github.com/davegomez tip-tldr: You may have a big list of names you need to filter in order to remove duplicates and sort them alphabetically.

c

  • /en/filtering-and-sorting-a-list-of-strings/

You may have a big list of names you need to filter in order to remove duplicates and sort them alphabetically.

In our example we are going to use the list of JavaScript reserved keywords we can find across the different versions of the language, but as you can notice, there is a lot of duplicated keywords and they are not alphabetically organized. So this is a perfect list (Array) of strings to test out this JavaScript tip.

var keywords = [
    'do',
    'if',
    'in',
    'for',
    'new',
    'try',
    'var',
    'case',
    'else',
    'enum',
    'null',
    'this',
    'true',
    'void',
    'with',
    'break',
    'catch',
    'class',
    'const',
    'false',
    'super',
    'throw',
    'while',
    'delete',
    'export',
    'import',
    'return',
    'switch',
    'typeof',
    'default',
    'extends',
    'finally',
    'continue',
    'debugger',
    'function',
    'do',
    'if',
    'in',
    'for',
    'int',
    'new',
    'try',
    'var',
    'byte',
    'case',
    'char',
    'else',
    'enum',
    'goto',
    'long',
    'null',
    'this',
    'true',
    'void',
    'with',
    'break',
    'catch',
    'class',
    'const',
    'false',
    'final',
    'float',
    'short',
    'super',
    'throw',
    'while',
    'delete',
    'double',
    'export',
    'import',
    'native',
    'public',
    'return',
    'static',
    'switch',
    'throws',
    'typeof',
    'boolean',
    'default',
    'extends',
    'finally',
    'package',
    'private',
    'abstract',
    'continue',
    'debugger',
    'function',
    'volatile',
    'interface',
    'protected',
    'transient',
    'implements',
    'instanceof',
    'synchronized',
    'do',
    'if',
    'in',
    'for',
    'let',
    'new',
    'try',
    'var',
    'case',
    'else',
    'enum',
    'eval',
    'null',
    'this',
    'true',
    'void',
    'with',
    'break',
    'catch',
    'class',
    'const',
    'false',
    'super',
    'throw',
    'while',
    'yield',
    'delete',
    'export',
    'import',
    'public',
    'return',
    'static',
    'switch',
    'typeof',
    'default',
    'extends',
    'finally',
    'package',
    'private',
    'continue',
    'debugger',
    'function',
    'arguments',
    'interface',
    'protected',
    'implements',
    'instanceof',
    'do',
    'if',
    'in',
    'for',
    'let',
    'new',
    'try',
    'var',
    'case',
    'else',
    'enum',
    'eval',
    'null',
    'this',
    'true',
    'void',
    'with',
    'await',
    'break',
    'catch',
    'class',
    'const',
    'false',
    'super',
    'throw',
    'while',
    'yield',
    'delete',
    'export',
    'import',
    'public',
    'return',
    'static',
    'switch',
    'typeof',
    'default',
    'extends',
    'finally',
    'package',
    'private',
    'continue',
    'debugger',
    'function',
    'arguments',
    'interface',
    'protected',
    'implements',
    'instanceof'
];

Since we don't want to change our original list, we are going to use a high order function named filter, which will return a new filter array based in a predicate (function) we pass to it. The predicate will compare the index of the current keyword in the original list with its index in the new list and will push it to the new array only if the indexes match.

Finally we are going to sort the filtered list using the sort function which takes a comparison function as the only argument, returning a alphabetically sorted list.

var filteredAndSortedKeywords = keywords
    .filter(function (keyword, index) {
        return keywords.lastIndexOf(keyword) === index;
    })
    .sort(function (a, b) {
        return a < b ? -1 : 1;
    });

The ES6 (ECMAScript 2015) version using arrow functions looks a little simpler:

const filteredAndSortedKeywords = keywords.filter((keyword, index) => keywords.lastIndexOf(keyword) === index).sort((a, b) => (a < b ? -1 : 1));

And this is the final filtered and sorted list of JavaScript reserved keywords:

console.log(filteredAndSortedKeywords);

// ['abstract', 'arguments', 'await', 'boolean', 'break', 'byte', 'case', 'catch', 'char', 'class', 'const', 'continue', 'debugger', 'default', 'delete', 'do', 'double', 'else', 'enum', 'eval', 'export', 'extends', 'false', 'final', 'finally', 'float', 'for', 'function', 'goto', 'if', 'implements', 'import', 'in', 'instanceof', 'int', 'interface', 'let', 'long', 'native', 'new', 'null', 'package', 'private', 'protected', 'public', 'return', 'short', 'static', 'super', 'switch', 'synchronized', 'this', 'throw', 'throws', 'transient', 'true', 'try', 'typeof', 'var', 'void', 'volatile', 'while', 'with', 'yield']

Thanks to @nikshulipa, @kirilloid, @lesterzone, @tracker1, @manuel_del_pozo for all the comments and suggestions!

title: Short circuit evaluation in JS. tip-number: 27 tip-username: bhaskarmelkani tip-username-profile: https://www.twitter.com/bhaskarmelkani tip-tldr: Short-circuit evaluation says, the second argument is executed or evaluated only if the first argument does not suffice to determine the value of the expression, when the first argument of the AND && function evaluates to false, the overall value must be false, and when the first argument of the OR || function evaluates to true, the overall value must be true.

  • /en/short-circuit-evaluation-in-js/

Short-circuit evaluation says, the second argument is executed or evaluated only if the first argument does not suffice to determine the value of the expression: when the first argument of the AND (&&) function evaluates to false, the overall value must be false; and when the first argument of the OR (||) function evaluates to true, the overall value must be true.

For the following test condition and isTrue and isFalse function.

var test = true;
var isTrue = function () {
    console.log('Test is true.');
};
var isFalse = function () {
    console.log('Test is false.');
};

Using logical AND - &&.

// A normal if statement.
if (test) {
    isTrue(); // Test is true
}

// Above can be done using '&&' as -

test && isTrue(); // Test is true

Using logical OR - ||.

test = false;
if (!test) {
    isFalse(); // Test is false.
}

test || isFalse(); // Test is false.

The logical OR could also be used to set a default value for function argument.

function theSameOldFoo(name) {
    name = name || 'Bar';
    console.log("My best friend's name is " + name);
}
theSameOldFoo(); // My best friend's name is Bar
theSameOldFoo('Bhaskar'); // My best friend's name is Bhaskar

The logical AND could be used to avoid exceptions when using properties of undefined. Example:

var dog = {
    bark: function () {
        console.log('Woof Woof');
    }
};

// Calling dog.bark();
dog.bark(); // Woof Woof.

// But if dog is not defined, dog.bark() will raise an error "Cannot read property 'bark' of undefined."
// To prevent this, we can use &&.

dog && dog.bark(); // This will only call dog.bark(), if dog is defined.

title: Currying vs partial application tip-number: 28 tip-username: bhaskarmelkani tip-username-profile: https://www.twitter.com/bhaskarmelkani tip-tldr: Currying and partial application are two ways of transforming a function into another function with a generally smaller arity.

  • /en/curry-vs-partial-application/

Currying

Currying takes a function

f: X * Y -> R

and turns it into a function

f': X -> (Y -> R)

Instead of calling f with two arguments, we invoke f' with the first argument. The result is a function that we then call with the second argument to produce the result.

Thus, if the uncurried f is invoked as

f(3,5)

then the curried f' is invoked as

f(3)(5)

For example: Uncurried add()

function add(x, y) {
    return x + y;
}

add(3, 5); // returns 8

Curried add()

function addC(x) {
    return function (y) {
        return x + y;
    };
}

addC(3)(5); // returns 8

The algorithm for currying.

Curry takes a binary function and returns a unary function that returns a unary function.

curry: (X × Y → R) → (X → (Y → R))

Javascript Code:

function curry(f) {
    return function (x) {
        return function (y) {
            return f(x, y);
        };
    };
}

Partial application

Partial application takes a function

f: X * Y -> R

and a fixed value for the first argument to produce a new function

f`: Y -> R

f' does the same as f, but only has to fill in the second parameter which is why its arity is one less than the arity of f.

For example: Binding the first argument of function add to 5 produces the function plus5.

function plus5(y) {
    return 5 + y;
}

plus5(3); // returns 8

The algorithm of partial application.*

partApply takes a binary function and a value and produces a unary function.

partApply : ((X × Y → R) × X) → (Y → R)

Javascript Code:

function partApply(f, x) {
    return function (y) {
        return f(x, y);
    };
}

title: Speed up recursive functions with memoization tip-number: 29 tip-username: hingsir tip-username-profile: https://github.com/hingsir tip-tldr: Fibonacci sequence is very familiar to everybody. we can write the following function in 20 seconds.it works, but not efficient. it did lots of duplicate computing works, we can cache its previously computed results to speed it up.

  • /en/speed-up-recursive-functions-with-memoization/

Fibonacci sequence is very familiar to everybody. We can write the following function in 20 seconds.

var fibonacci = function (n) {
    return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
};

It works, but is not efficient. It did lots of duplicate computing works, we can cache its previously computed results to speed it up.

var fibonacci = (function () {
    var cache = [0, 1]; // cache the value at the n index
    return function (n) {
        if (cache[n] === undefined) {
            for (var i = cache.length; i <= n; ++i) {
                cache[i] = cache[i - 1] + cache[i - 2];
            }
        }
        return cache[n];
    };
})();

Also, we can define a higher-order function that accepts a function as its argument and returns a memoized version of the function.

var memoize = function (func) {
    var cache = {};
    return function () {
        var key = JSON.stringify(Array.prototype.slice.call(arguments));
        return key in cache ? cache[key] : (cache[key] = func.apply(this, arguments));
    };
};
fibonacci = memoize(fibonacci);

And this is an ES6 version of the memoize function.

var memoize = function (func) {
    const cache = {};
    return (...args) => {
        const key = JSON.stringify(args);
        return key in cache ? cache[key] : (cache[key] = func(...args));
    };
};
fibonacci = memoize(fibonacci);

we can use memoize() in many other situations

  • GCD(Greatest Common Divisor)
var gcd = memoize(function (a, b) {
    var t;
    if (a < b) (t = b), (b = a), (a = t);
    while (b != 0) (t = b), (b = a % b), (a = t);
    return a;
});
gcd(27, 183); //=> 3
  • Factorial calculation
var factorial = memoize(function (n) {
    return n <= 1 ? 1 : n * factorial(n - 1);
});
factorial(5); //=> 120

Learn more about memoization:

title: Converting truthy/falsy values to boolean tip-number: 30 tip-username: hakhag tip-username-profile: https://github.com/hakhag tip-tldr: Logical operators are a core part of JavaScript, here you can see a a way you always get a true or false no matter what was given to it.

  • /en/converting-truthy-falsy-values-to-boolean/

You can convert a truthy or falsy value to true boolean with the !! operator.

!!''; // false
!!0; // false
!!null; // false
!!undefined; // false
!!NaN; // false

!!'hello'; // true
!!1; // true
!!{}; // true
!![]; // true

title: Avoid modifying or passing arguments into other functions — it kills optimization tip-number: 31 tip-username: berkana tip-username-profile: https://github.com/berkana tip-tldr: Within JavaScript functions, the variable name arguments lets you access all of the arguments passed to the function. arguments is an array-like object; arguments can be accessed using array notation, and it has the length property, but it doesn't have many of the built-in methods that arrays have such as filter and map and forEach. Because of this, it is a fairly common practice to convert arguments into an array using the following snipet

  • /en/avoid-modifying-or-passing-arguments-into-other-functions-it-kills-optimization/

###Background

Within JavaScript functions, the variable name arguments lets you access all of the arguments passed to the function. arguments is an array-like object; arguments can be accessed using array notation, and it has the length property, but it doesn't have many of the built-in methods that arrays have such as filter and map and forEach. Because of this, it is a fairly common practice to convert arguments into an array using the following:

var args = Array.prototype.slice.call(arguments);

This calls the slice method from the Array prototype, passing it arguments; the slice method returns a shallow copy of arguments as a new array object. A common shorthand for this is :

var args = [].slice.call(arguments);

In this case, instead of calling slice from the Array prototype, it is simply being called from an empty array literal.

###Optimization

Unfortunately, passing arguments into any function call will cause the V8 JavaScript engine used in Chrome and Node to skip optimization on the function that does this, which can result in considerably slower performance. See this article on optimization killers. Passing arguments to any other function is known as leaking arguments.

Instead, if you want an array of the arguments that lets you use you need to resort to this:

var args = new Array(arguments.length);
for (var i = 0; i < args.length; ++i) {
    args[i] = arguments[i];
}

Yes it is more verbose, but in production code, it is worth it for the performance optimization.

title: Map() to the rescue; adding order to Object properties tip-number: 32 tip-username: loverajoel tip-username-profile: https://twitter.com/loverajoel tip-tldr: An Object it is an unordered collection of properties... that means that if you are trying to save ordered data inside an Object, you have to review it because properties order in objects are not guaranteed. tip-writer-support: https://www.coinbase.com/loverajoel

  • /en/map-to-the-rescue-adding-order-to-object-properties/

Object properties order

An object is a member of the type Object. It is an unordered collection of properties each of which contains a primitive value, object, or function. A function stored in a property of an object is called a method. ECMAScript

Take a look in action

var myObject = {
	z: 1,
	'@': 2,
	b: 3,
	1: 4,
	5: 5
};
console.log(myObject) // Object {1: 4, 5: 5, z: 1, @: 2, b: 3}

for (item in myObject) {...
// 1
// 5
// z
// @
// b

Each browser have his own rules about the order in objects bebause technically, order is unspecified.

How to solve this?

Map

Using a new ES6 feature called Map. A Map object iterates its elements in insertion order — a for...of loop returns an array of [key, value] for each iteration.

var myObject = new Map();
myObject.set('z', 1);
myObject.set('@', 2);
myObject.set('b', 3);
for (var [key, value] of myObject) {
  console.log(key, value);
...
// z 1
// @ 2
// b 3

Hack for old browsers

Mozilla suggest:

So, if you want to simulate an ordered associative array in a cross-browser environment, you are forced to either use two separate arrays (one for the keys and the other for the values), or build an array of single-property objects, etc.

// Using two separate arrays
var objectKeys = [z, @, b, 1, 5];
for (item in objectKeys) {
	myObject[item]
...

// Build an array of single-property objects
var myData = [{z: 1}, {'@': 2}, {b: 3}, {1: 4}, {5: 5}];

title: Create array sequence [0, 1, ..., N-1] in one line tip-number: 33 tip-username: SarjuHansaliya tip-username-profile: https://github.com/SarjuHansaliya tip-tldr: Compact one-liners that generate ordinal sequence arrays

  • /en/create-range-0...n-easily-using-one-line/

Here are two compact code sequences to generate the N-element array [0, 1, ..., N-1]:

Solution 1 (requires ES5)

Array.apply(null, { length: N }).map(Function.call, Number);

Brief explanation

  1. Array.apply(null, {length: N}) returns an N-element array filled with undefined (i.e. A = [undefined, undefined, ...]).
  2. A.map(Function.call, Number) returns an N-element array, whose index I gets the result of Function.call.call(Number, undefined, I, A)
  3. Function.call.call(Number, undefined, I, A) collapses into Number(I), which is naturally I.
  4. Result: [0, 1, ..., N-1].

For a more thorough explanation, go here.

Solution 2 (requires ES6)

It uses Array.from https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/from

Array.from(new Array(N), (val, index) => index);

Solution 3 (requires ES6)

Array.from(Array(N).keys());

Brief explanation

  1. A = new Array(N) returns an array with N holes (i.e. A = [,,,...], but A[x] = undefined for x in 0...N-1).
  2. F = (val,index)=>index is simply function F (val, index) { return index; }
  3. Array.from(A, F) returns an N-element array, whose index I gets the results of F(A[I], I), which is simply I.
  4. Result: [0, 1, ..., N-1].

One More Thing

If you actually want the sequence [1, 2, ..., N], Solution 1 becomes:

Array.apply(null, { length: N }).map(function (value, index) {
    return index + 1;
});

and Solution 2:

Array.from(new Array(N), (val, index) => index + 1);

title: Implementing asynchronous loop tip-number: 34 tip-username: madmantalking tip-username-profile: https://github.com/madmantalking tip-tldr: You may run into problems while implementing asynchronous loops.

  • /en/implementing-asynchronous-loops/

Let's try out writing an asynchronous function which prints the value of the loop index every second.

for (var i = 0; i < 5; i++) {
    setTimeout(function () {
        console.log(i);
    }, 1000 * (i + 1));
}

The output of the above programs turns out to be

> 5
> 5
> 5
> 5
> 5

So this definitely doesn't work.

Reason

Each timeout refers to the original i, not a copy. So the for loop increments i until it gets to 5, then the timeouts run and use the current value of i (which is 5).

Well , this problem seems easy. An immediate solution that strikes is to cache the loop index in a temporary variable.

for (var i = 0; i < 5; i++) {
    var temp = i;
    setTimeout(function () {
        console.log(temp);
    }, 1000 * (i + 1));
}

But again the output of the above programs turns out to be

> 4
> 4
> 4
> 4
> 4

So , that doesn't work either , because blocks don't create a scope and variables initializers are hoisted to the top of the scope. In fact, the previous block is the same as:

var temp;
for (var i = 0; i < 5; i++) {
    temp = i;
    setTimeout(function () {
        console.log(temp);
    }, 1000 * (i + 1));
}

Solution

There are a few different ways to copy i. The most common way is creating a closure by declaring a function and passing i as an argument. Here we do this as a self-calling function.

for (var i = 0; i < 5; i++) {
    (function (num) {
        setTimeout(function () {
            console.log(num);
        }, 1000 * (i + 1));
    })(i);
}

In JavaScript, arguments are passed by value to a function. So primitive types like numbers, dates, and strings are basically copied. If you change them inside the function, it does not affect the outside scope. Objects are special: if the inside function changes a property, the change is reflected in all scopes.

Another approach for this would be with using let. With ES6 the let keyword is useful since it's block scoped unlike var

for (let i = 0; i < 5; i++) {
    setTimeout(function () {
        console.log(i);
    }, 1000 * (i + 1));
}

title: Assignment Operators tip-number: 35 tip-username: hsleonis tip-username-profile: https://github.com/hsleonis tip-tldr: Assigning is very common. Sometimes typing becomes time consuming for us 'Lazy programmers'. So, we can use some tricks to help us and make our code cleaner and simpler.

  • /en/assignment-shorthands/

Assigning is very common. Sometimes typing becomes time consuming for us 'Lazy programmers'. So, we can use some tricks to help us and make our code cleaner and simpler.

This is the similar use of

x += 23; // x = x + 23;
y -= 15; // y = y - 15;
z *= 10; // z = z * 10;
k /= 7; // k = k / 7;
p %= 3; // p = p % 3;
d **= 2; // d = d ** 2;
m >>= 2; // m = m >> 2;
n <<= 2; // n = n << 2;
n++; // n = n + 1;
n--;
n = n - 1;

++ and -- operators

There is a special ++ operator. It's best to explain it with an example:

var a = 2;
var b = a++;
// Now a is 3 and b is 2

The a++ statement does this:

  1. return the value of a
  2. increment a by 1

But what if we wanted to increment the value first? It's simple:

var a = 2;
var b = ++a;
// Now both a and b are 3

See? I put the operator before the variable.

The -- operator is similar, except it decrements the value.

If-else (Using ternary operator)

This is what we write on regular basis.

var newValue;
if (value > 10) newValue = 5;
else newValue = 2;

We can user ternary operator to make it awesome:

var newValue = value > 10 ? 5 : 2;

Null, Undefined, Empty Checks

if (variable1 !== null || variable1 !== undefined || variable1 !== '') {
    var variable2 = variable1;
}

Shorthand here:

var variable2 = variable1 || '';

P.S.: If variable1 is a number, then first check if it is 0.

Object Array Notation

Instead of using:

var a = new Array();
a[0] = 'myString1';
a[1] = 'myString2';

Use this:

var a = ['myString1', 'myString2'];

Associative array

Instead of using:

var skillSet = new Array();
skillSet['Document language'] = 'HTML5';
skillSet['Styling language'] = 'CSS3';

Use this:

var skillSet = {
    'Document language': 'HTML5',
    'Styling language': 'CSS3'
};

title: Observe DOM changes in extensions tip-number: 36 tip-username: beyondns tip-username-profile: https://github.com/beyondns tip-tldr: When you develop extensions to existent sites it's not so easy to play with DOM 'cause of modern dynamic javascript.

  • /en/observe-dom-changes/

MutationObserver is a solution to listen DOM changes and do what you want to do with elements when they changed. In following example there is some emulation of dynamic content loading with help of timers, after first "target" element creation goes "subTarget". In extension code firstly rootObserver works till targetElement appearance then elementObserver starts. This cascading observing helps finally get moment when subTargetElement found. This useful to develop extensions to complex sites with dynamic content loading.

const observeConfig = {
    attributes: true,
    childList: true,
    characterData: true,
    subtree: true
};

function initExtension(rootElement, targetSelector, subTargetSelector) {
    var rootObserver = new MutationObserver(function (mutations) {
        console.log('Inside root observer');
        targetElement = rootElement.querySelector(targetSelector);
        if (targetElement) {
            rootObserver.disconnect();
            var elementObserver = new MutationObserver(function (mutations) {
                console.log('Inside element observer');
                subTargetElement = targetElement.querySelector(subTargetSelector);
                if (subTargetElement) {
                    elementObserver.disconnect();
                    console.log('subTargetElement found!');
                }
            });
            elementObserver.observe(targetElement, observeConfig);
        }
    });
    rootObserver.observe(rootElement, observeConfig);
}

(function () {
    initExtension(document.body, 'div.target', 'div.subtarget');

    setTimeout(function () {
        del = document.createElement('div');
        del.innerHTML = "<div class='target'>target</div>";
        document.body.appendChild(del);
    }, 3000);

    setTimeout(function () {
        var el = document.body.querySelector('div.target');
        if (el) {
            del = document.createElement('div');
            del.innerHTML = "<div class='subtarget'>subtarget</div>";
            el.appendChild(del);
        }
    }, 5000);
})();

title: Deduplicate an Array tip-number: 37 tip-username: danillouz tip-username-profile: https://www.twitter.com/danillouz tip-tldr: How to remove duplicate elements, of different data types, from an Array.

  • /en/deduplicate-an-array/

Primitives

If an Array only contains primitive values, we can deduplicate it by only using the filter and indexOf methods.

var deduped = [1, 1, 'a', 'a'].filter(function (el, i, arr) {
    return arr.indexOf(el) === i;
});

console.log(deduped); // [ 1, 'a' ]

ES2015

We can write this in a more compact way using an arrow function.

var deduped = [1, 1, 'a', 'a'].filter((el, i, arr) => arr.indexOf(el) === i);

console.log(deduped); // [ 1, 'a' ]

But with the introduction of Sets and the from method, we can achieve the same result in a more concise way.

var deduped = Array.from(new Set([1, 1, 'a', 'a']));

console.log(deduped); // [ 1, 'a' ]

Objects

We can't use the same approach when the elements are Objects, because Objects are stored by reference and primitives are stored by value.

1 === 1 // true

'a' === 'a' // true

{ a: 1 } === { a: 1 } // false

Therefore we need to change our approach and use a hash table.

function dedup(arr) {
    var hashTable = {};

    return arr.filter(function (el) {
        var key = JSON.stringify(el);
        var match = Boolean(hashTable[key]);

        return match ? false : (hashTable[key] = true);
    });
}

var deduped = dedup([{ a: 1 }, { a: 1 }, [1, 2], [1, 2]]);

console.log(deduped); // [ {a: 1}, [1, 2] ]

Because a hash table in javascript is simply an Object, the keys will always be of the type String. This means that normally we can't distinguish between strings and numbers of the same value, i.e. 1 and '1'.

var hashTable = {};

hashTable[1] = true;
hashTable['1'] = true;

console.log(hashTable); // { '1': true }

However, because we're using JSON.stringify, keys that are of the type String, will be stored as an escaped string value, giving us unique keys in our hashTable.

var hashTable = {};

hashTable[JSON.stringify(1)] = true;
hashTable[JSON.stringify('1')] = true;

console.log(hashTable); // { '1': true, '\'1\'': true }

This means duplicate elements of the same value, but of a different type, will still be deduplicated using the same implementation.

var deduped = dedup([{ a: 1 }, { a: 1 }, [1, 2], [1, 2], 1, 1, '1', '1']);

console.log(deduped); // [ {a: 1}, [1, 2], 1, '1' ]

Resources

Methods

ES2015

Stack overflow

title: Flattening multidimensional Arrays in JavaScript tip-number: 38 tip-username: loverajoel tip-username-profile: https://www.twitter.com/loverajoel tip-tldr: Three different solutions to merge multidimensional array into a single array. tip-writer-support: https://www.coinbase.com/loverajoel

  • /en/flattening-multidimensional-arrays-in-javascript/

These are the three known ways to merge multidimensional array into a single array.

Given this array:

var myArray = [
    [1, 2],
    [3, 4, 5],
    [6, 7, 8, 9]
];

We wanna have this result:

[1, 2, 3, 4, 5, 6, 7, 8, 9];

Solution 1: Using concat() and apply()

var myNewArray = [].concat.apply([], myArray);
// [1, 2, 3, 4, 5, 6, 7, 8, 9]

Solution 2: Using reduce()

var myNewArray = myArray.reduce(function (prev, curr) {
    return prev.concat(curr);
});
// [1, 2, 3, 4, 5, 6, 7, 8, 9]

Solution 3:

var myNewArray3 = [];
for (var i = 0; i < myArray.length; ++i) {
    for (var j = 0; j < myArray[i].length; ++j) myNewArray3.push(myArray[i][j]);
}
console.log(myNewArray3);
// [1, 2, 3, 4, 5, 6, 7, 8, 9]

Solution 4: Using spread operator in ES6

var myNewArray4 = [].concat(...myArray);
console.log(myNewArray4);
// [1, 2, 3, 4, 5, 6, 7, 8, 9]

Solution 5: Using flat() in ES10

var myNewArray5 = myArray.flat();
console.log(myNewArray5);
// [1, 2, 3, 4, 5, 6, 7, 8, 9]

Take a look here these 4 algorithms in action.

For infinitely nested array try Lodash flattenDeep().

If you are curious about performance, here a test for check how it works.

title: Advanced Javascript Properties tip-number: 39 tip-username: mallowigi tip-username-profile: https://github.com/mallowigi tip-tldr: How to add private properties, getters and setters to objects.

  • /en/advanced-properties/

It is possible to configure object properties in Javascript for example to set properties to be pseudo-private or readonly. This feature is available since ECMAScript 5.1, therefore supported by all recent browsers.

To do so, you need to use the method defineProperty of the Object prototype like so:

var a = {};
Object.defineProperty(a, 'readonly', {
    value: 15,
    writable: false
});

a.readonly = 20;
console.log(a.readonly); // 15

The syntax is as follows:

Object.defineProperty(dest, propName, options);

or for multiple definitions:

Object.defineProperties(dest, {
    propA: optionsA,
    propB: optionsB //...
});

where options include the following attributes:

  • value: if the property is not a getter (see below), value is a mandatory attribute. {a: 12} === Object.defineProperty(obj, 'a', {value: 12})
  • writable: set the property as readonly. Note that if the property is a nested objects, its properties are still editable.
  • enumerable: set the property as hidden. That means that for ... of loops and stringify will not include the property in their result, but the property is still there. Note: That doesn't mean that the property is private! It can still be accessible from the outside, it just means that it won't be printed.
  • configurable: set the property as non modifiable, e.g. protected from deletion or redefinition. Again, if the property is a nested object, its properties are still configurable.

So in order to create a private constant property, you can define it like so:

Object.defineProperty(obj, 'myPrivateProp', { value: val, enumerable: false, writable: false, configurable: false });

Besides configuring properties, defineProperty allows us to define dynamic properties, thanks to the second parameter being a string. For instance, let's say that I want to create properties according to some external configuration:

var obj = {
  getTypeFromExternal(): true // illegal in ES5.1
}

Object.defineProperty(obj, getTypeFromExternal(), {value: true}); // ok

// For the example sake, ES6 introduced a new syntax:
var obj = {
  [getTypeFromExternal()]: true
}

But that's not all! Advanced properties allows us to create getters and setters, just like other OOP languages! In that case, one cannot use the writable, enumerable and configurable properties, but instead:

function Foobar () {
  var _foo; //  true private property

  Object.defineProperty(obj, 'foo', {
    get: function () { return _foo; }
    set: function (value) { _foo = value }
  });

}

var foobar = new Foobar();
foobar.foo; // 15
foobar.foo = 20; // _foo = 20

Aside for the obvious advantage of encapsulation and advanced accessors, you will notice that we didn't "call" the getter, instead we just "get" the property without parentheses! This is awesome! For instance, let's imagine that we have an object with long nested properties, like so:

var obj = { a: { b: { c: [{ d: 10 }, { d: 20 }] } } };

Now instead of doing a.b.c[0].d (where one of the properties can resolve to undefined and throw an error), we can instead create an alias:

Object.defineProperty(obj, 'firstD', {
    get: function () {
        return a && a.b && a.b.c && a.b.c[0] && a.b.c[0].d;
    }
});

console.log(obj.firstD); // 10

Note

If you define a getter without a setter and still try to set a value, you will get an error! This is particularly important when using helper functions such as $.extend or _.merge. Be careful!

Links

title: Using JSON.Stringify tip-number: 40 tip-username: vamshisuram tip-username-profile: https://github.com/vamshisuram tip-tldr: Create string from selected properties of JSON object.

  • /en/using-json-stringify/

Let's say there is an object with properties "prop1", "prop2", "prop3". We can pass additional params to JSON.stringify to selectively write properties of the object to string like:

var obj = {
    prop1: 'value1',
    prop2: 'value2',
    prop3: 'value3'
};

var selectedProperties = ['prop1', 'prop2'];

var str = JSON.stringify(obj, selectedProperties);

// str
// {"prop1":"value1","prop2":"value2"}

The "str" will contain only info on selected properties only.

Instead of array we can pass a function also.

function selectedProperties(key, val) {
    // the first val will be the entire object, key is empty string
    if (!key) {
        return val;
    }

    if (key === 'prop1' || key === 'prop2') {
        return val;
    }

    return;
}

The last optional param it takes is to modify the way it writes the object to string.

var str = JSON.stringify(obj, selectedProperties, '\t\t');

/* str output with double tabs in every line.
{
        "prop1": "value1",
        "prop2": "value2"
}
*/

title: Array average and median tip-number: 41 tip-username: soyuka tip-username-profile: https://github.com/soyuka tip-tldr: Calculate the average and median from array values

  • /en/array-average-and-median/

The following examples will be based on the following array:

let values = [2, 56, 3, 41, 0, 4, 100, 23];

To get the average, we have to sum up numbers and then divide by the number of values. Steps are:

  • get the array length
  • sum up values
  • get the average (sum/length)
let values = [2, 56, 3, 41, 0, 4, 100, 23];
let sum = values.reduce((previous, current) => (current += previous));
let avg = sum / values.length;
// avg = 28

Or:

let values = [2, 56, 3, 41, 0, 4, 100, 23];
let count = values.length;
values = values.reduce((previous, current) => (current += previous));
values /= count;
// avg = 28

Now, to get the median steps are:

  • sort the array
  • get the arethmic mean of the middle values
let values = [2, 56, 3, 41, 0, 4, 100, 23];
values.sort((a, b) => a - b);
let lowMiddle = Math.floor((values.length - 1) / 2);
let highMiddle = Math.ceil((values.length - 1) / 2);
let median = (values[lowMiddle] + values[highMiddle]) / 2;
// median = 13,5

With a bitwise operator:

let values = [2, 56, 3, 41, 0, 4, 100, 23];
values.sort((a, b) => a - b);
let median = (values[(values.length - 1) >> 1] + values[values.length >> 1]) / 2;
// median = 13,5

title: Preventing Unapply Attacks tip-number: 42 tip-username: emars tip-username-profile: https://twitter.com/marseltov tip-tldr: Freeze the builtin prototypes.

  • /en/preventing-unapply-attacks/

By overriding the builtin prototypes, external code can cause code to break by rewriting code to expose and change bound arguments. This can be an issue that seriously breaks applications that works by using polyfill es5 methods.

// example bind polyfill
function bind(fn) {
    var prev = Array.prototype.slice.call(arguments, 1);
    return function bound() {
        var curr = Array.prototype.slice.call(arguments, 0);
        var args = Array.prototype.concat.apply(prev, curr);
        return fn.apply(null, args);
    };
}

// unapply-attack
function unapplyAttack() {
    var concat = Array.prototype.concat;
    Array.prototype.concat = function replaceAll() {
        Array.prototype.concat = concat; // restore the correct version
        var curr = Array.prototype.slice.call(arguments, 0);
        var result = concat.apply([], curr);
        return result;
    };
}

The above function discards the prev array from the bind meaning that any .concat the first concat call following using the unapply attack will throw an error.

By using Object.freeze, making an object immutable, you prevent any overriding of the builtin object prototypes.

(function freezePrototypes() {
    if (typeof Object.freeze !== 'function') {
        throw new Error('Missing Object.freeze');
    }
    Object.freeze(Object.prototype);
    Object.freeze(Array.prototype);
    Object.freeze(Function.prototype);
})();

You can read more about unapply attacks here. Although this concept is called an 'unapply attack' due to some code being able to access closures that normally wouldn't be in scope, it is mostly wrong to consider this a security feature due to it not preventing an attacker with code execution from extending prototypes before the freezing happens and also still having the potential to read all scopes using various language features. ECMA modules would give realm based isolation which is much stronger than this solution however still doesn't fix the issues of third party scripts.

title: Use destructuring in function parameters tip-number: 43 tip-username: dislick tip-username-profile: https://github.com/dislick tip-tldr: Did you know that you can use destructuring in function parameters?

  • /en/use-destructuring-in-function-parameters/

I am sure many of you are already familiar with the ES6 Destructuring Assignment. Did you know that you can also use it in function parameters?

var sayHello = function ({ name, surname }) {
    console.log(`Hello ${name} ${surname}! How are you?`);
};

sayHello({ name: 'John', surname: 'Smith' });
// -> Hello John Smith! How are you?

This is great for functions which accept an options object. For this use case, you can also add default parameters to fill in whatever values the caller leaves out, or if the caller forgets to pass one at all:

var sayHello2 = function ({ name = 'Anony', surname = 'Moose' } = {}) {
    console.log(`Hello ${name} ${surname}! How are you?`);
};

The = {} says that the default object to be destructured for this parameter is {}, in case the caller forgets to pass the parameter, or passes one of the wrong type (more on this below).

sayHello2();
// -> Hello Anony Moose! How are you?
sayHello2({ name: 'Bull' });
// -> Hello Bull Moose! How are you?
Argument Handling

With plain destructuring assignment, if the the input parameter can't be matched with the function's specified object arguments, all the unmatched arguments are undefined, so you need to add code that handles this properly:

var sayHelloTimes = function ({ name, surname }, times) {
    console.log(`Hello ${name} ${surname}! I've seen you ${times} times before.`);
};

sayHelloTimes({ name: 'Pam' }, 5678);
// -> Hello Pam undefined! I've seen you 5678 times before.
sayHelloTimes(5678);
// -> Hello undefined undefined! I've seen you undefined times before.

Worse, if the parameter to be destructured is missing, an exception is thrown, probably bringing your app to a screeching halt:

sayHelloTimes();
// -> Uncaught TypeError: Cannot match against 'undefined' or 'null'...

It's conceptually similar to accessing a property of an undefined object, just with a different exception type.

Destructuring assignment with default parameters hides all the above to a certain extent:

var sayHelloTimes2 = function ({ name = 'Anony', surname = 'Moose' } = {}, times) {
    console.log(`Hello ${name} ${surname}! I've seen you ${times} times before.`);
};

sayHelloTimes2({ name: 'Pam' }, 5678);
// -> Hello Pam Moose! I've seen you 5678 times before.
sayHelloTimes2(5678);
// -> Hello Anony Moose! I've seen you undefined times before.
sayHelloTimes2();
// -> Hello Anony Moose! I've seen you undefined times before.

As for = {}, it covers the case of a missing object, for which individual property defaults won't help at all:

var sayHelloTimes2a = function ({ name = 'Anony', surname = 'Moose' }, times) {
    console.log(`Hello ${name} ${surname}! I've seen you ${times} times before.`);
};

sayHelloTimes2a({ name: 'Pam' }, 5678);
// -> Hello Pam Moose! I've seen you 5678 times before.
sayHelloTimes2a(5678);
// -> Hello Anony Moose! I've seen you undefined times before.
sayHelloTimes2a();
// -> Uncaught TypeError: Cannot match against 'undefined' or 'null'.
Availability

Note that destructuring assignment may not yet be available by default, in the version of Node.js or browser that you're using. For Node.js, you can try using the --harmony-destructuring flag on startup to activate this feature.

title: Know the passing mechanism tip-number: 44 tip-username: bmkmanoj tip-username-profile: https://github.com/bmkmanoj tip-tldr: JavaScript technically only passes by value for both primitives and object (or reference) types. In case of reference types the reference value itself is passed by value.

  • /en/know-the-passing-mechanism/

JavaScript is pass-by-value, technically. It is neither pass-by-value nor pass-by-reference, going by the truest sense of these terms. To understand this passing mechanism, take a look at the following two example code snippets and the explanations.

Example 1

var me = {
    // 1
    partOf: 'A Team'
};

function myTeam(me) {
    // 2

    me = {
        // 3
        belongsTo: 'A Group'
    };
}

myTeam(me);
console.log(me); // 4  : {'partOf' : 'A Team'}

In above example, when the myTeam gets invoked, JavaScript is passing the reference to me object as value, as it is an object and invocation itself creates two independent references to the same object, (though the name being same here i.e. me, is misleading and gives us an impression that it is the single reference) and hence, the reference variable themselves are independent.

When we assigned a new object at #3, we are changing this reference value entirely within the myTeam function, and it will not have any impact on the original object outside this function scope, from where it was passed and the reference in the outside scope is going to retain the original object and hence the output from #4.

Example 2

var me = {
    // 1
    partOf: 'A Team'
};

function myGroup(me) {
    // 2
    me.partOf = 'A Group'; // 3
}

myGroup(me);
console.log(me); // 4  : {'partOf' : 'A Group'}

In the case of myGroup invocation, we are passing the object me. But unlike the example 1 scenario, we are not assigning this me variable to any new object, effectively meaning the object reference value within the myGroup function scope still is the original object's reference value and when we are modifying the property within this scope, it is effectively modifying the original object's property. Hence, you get the output from #4.

So does this later case not prove that javascript is pass-by-reference? No, it does not. Remember, JavaScript passes the reference as value, in case of objects. The confusion arises as we tend not to understand fully what pass by reference is. This is the exact reason, some prefer to call this as call-by-sharing.

Initially posted by the author on js-by-examples

title: Calculate the Max/Min value from an array tip-number: 45 tip-username: loverajoel tip-username-profile: https://www.twitter.com/loverajoel tip-tldr: Ways to use the built-in functions Math.max() and Math.min() with arrays of numbers tip-writer-support: https://www.coinbase.com/loverajoel

  • /en/calculate-the-max-min-value-from-an-array/

The built-in functions Math.max() and Math.min() find the maximum and minimum value of the arguments, respectively.

Math.max(1, 2, 3, 4); // 4
Math.min(1, 2, 3, 4); // 1

These functions will not work as-is with arrays of numbers. However, there are some ways around this.

Function.prototype.apply() allows you to call a function with a given this value and an array of arguments.

var numbers = [1, 2, 3, 4];
Math.max.apply(null, numbers); // 4
Math.min.apply(null, numbers); // 1

Passing the numbers array as the second argument of apply() results in the function being called with all values in the array as parameters.

A simpler, ES2015 way of accomplishing this is with the new spread operator.

var numbers = [1, 2, 3, 4];
Math.max(...numbers); // 4
Math.min(...numbers); // 1

This operator causes the values in the array to be expanded, or "spread", into the function's arguments.

title: Detect document ready in pure JS tip-number: 46 tip-username: loverajoel tip-username-profile: https://www.twitter.com/loverajoel tip-tldr: The cross-browser way to check if the document has loaded in pure JavaScript tip-writer-support: https://www.coinbase.com/loverajoel

  • /en/detect-document-ready-in-pure-js/

The cross-browser way to check if the document has loaded in pure JavaScript is using readyState.

if (document.readyState === 'complete') {
    // The page is fully loaded
}

You can detect when the document is ready...

let stateCheck = setInterval(() => {
    if (document.readyState === 'complete') {
        clearInterval(stateCheck);
        // document ready
    }
}, 100);

or with onreadystatechange...

document.onreadystatechange = () => {
    if (document.readyState === 'complete') {
        // document ready
    }
};

Use document.readyState === 'interactive' to detect when the DOM is ready.

title: Basics declarations tip-number: 47 tip-username: adaniloff tip-username-profile: https://github.com/adaniloff tip-tldr: Understand and work with declarations.

  • /en/basics-declarations/

Below, different ways to declare variables in JavaScript. Comments and console.log should be enough to explain what's happening here:

var y,
    x = (y = 1); //== var x; var y; x = y = 1
console.log('--> 1:', `x = ${x}, y = ${y}`);

// Will print
//--> 1: x = 1, y = 1

First, we just set two variables. Nothing much here.

(() => {
    var x = (y = 2); // == var x; x = y = 2;
    console.log('2.0:', `x = ${x}, y = ${y}`);
})();
console.log('--> 2.1:', `x = ${x}, y = ${y}`);

// Will print
//2.0: x = 2, y = 2
//--> 2.1: x = 1, y = 2

As you can see, the code has only changed the global y, as we haven't declared the variable in the closure.

(() => {
    var x,
        y = 3; // == var x; var y = 3;
    console.log('3.0:', `x = ${x}, y = ${y}`);
})();
console.log('--> 3.1:', `x = ${x}, y = ${y}`);

// Will print
//3.0: x = undefined, y = 3
//--> 3.1: x = 1, y = 2

Now we declare both variables through var. Meaning they only live in the context of the closure.

(() => {
    var y,
        x = (y = 4); // == var x; var y; x = y = 4
    console.log('4.0:', `x = ${x}, y = ${y}`);
})();
console.log('--> 4.1:', `x = ${x}, y = ${y}`);

// Will print
//4.0: x = 4, y = 4
//--> 4.1: x = 1, y = 2

Both variables have been declared using var and only after that we've set their values. As local > global, x and y are local in the closure, meaning the global x and y are untouched.

x = 5; // == x = 5
console.log('--> 5:', `x = ${x}, y = ${y}`);

// Will print
//--> 5: x = 5, y = 2

This last line is explicit by itself.

You can test this and see the result thanks to babel.

More informations available on the MDN.

Special thanks to @kurtextrem for his collaboration :)!

title: How to reduce() arrays tip-number: 48 tip-username: darul75 tip-username-profile: https://twitter.com/darul75 tip-tldr: Some reminders about using reduce()

  • /en/reminders-about-reduce-function-usage/

As written in documentation the reduce() method applies a function against an accumulator and each value of the array (from left-to-right) to reduce it to a single value.

Signature

reduce() function accepts 2 parameters (M: mandatory, O: optional):

  • (M) a callback reducer function to be applied that deals with a pair of previous (result of previous computation) and next element until end of the list.
  • (O) an initial value to be used as the first argument to the first call of the callback.

So let's see a common usage and later a more sophisticated one.

Common usage (accumulation, concatenation)

We are on Amazon website (prices in $) and our caddy is quite full, let's compute total.

// my current amazon caddy purchases
var items = [{ price: 10 }, { price: 120 }, { price: 1000 }];

// our reducer function
var reducer = function add(sumSoFar, item) {
    return sumSoFar + item.price;
};

// do the job
var total = items.reduce(reducer, 0);

console.log(total); // 1130

Optional reduce function parameter was primitive integer type 0 in that first case, but it could have been an Object, an Array...instead of a primitive type, but we will see that later.

Now, cool I received a discount coupon of 20$.

var total = items.reduce(reducer, -20);

console.log(total); // 1110

Advanced usage (combination)

This second usage example is inspired by Redux combineReducers function source.

Idea behind is to separate reducer function into separate individual functions and at the end compute a new single big reducer function.

To illustrate this, let's create a single object literal with some reducers function able to compute total prices in different currency $, €...

var reducers = {
    totalInDollar: function (state, item) {
        // specific statements...
        return (state.dollars += item.price);
    },
    totalInEuros: function (state, item) {
        return (state.euros += item.price * 0.897424392);
    },
    totalInPounds: function (state, item) {
        return (state.pounds += item.price * 0.692688671);
    },
    totalInYen: function (state, item) {
        return (state.yens += item.price * 113.852);
    }
    // more...
};

Then, we create a new swiss knife function

  • responsible for applying each partial reduce functions.
  • that will return a new callback reducer function
var combineTotalPriceReducers = function (reducers) {
    return function (state, item) {
        return Object.keys(reducers).reduce(function (nextState, key) {
            reducers[key](state, item);
            return state;
        }, {});
    };
};

Now let's see how using it.

var bigTotalPriceReducer = combineTotalPriceReducers(reducers);

var initialState = { dollars: 0, euros: 0, yens: 0, pounds: 0 };

var totals = items.reduce(bigTotalPriceReducer, initialState);

console.log(totals);

/*
Object {dollars: 1130, euros: 1015.11531904, yens: 127524.24, pounds: 785.81131152}
*/

I hope this approach can give you another idea of using reduce() function for your own needs.

Your reduce function could handle an history of each computation by instance as it is done in Ramdajs with scan function

JSFiddle to play with

title: Easiest way to extract unix timestamp in JS tip-number: 49 tip-username: nmrony tip-username-profile: https://github.com/nmrony tip-tldr: In Javascript you can easily get the unix timestamp

  • /en/extract-unix-timestamp-easily/

We frequently need to calculate with unix timestamp. There are several ways to grab the timestamp. For current unix timestamp easiest and fastest way is

const dateTime = Date.now();
const timestamp = Math.floor(dateTime / 1000);

or

const dateTime = new Date().getTime();
const timestamp = Math.floor(dateTime / 1000);

To get unix timestamp of a specific date pass YYYY-MM-DD or YYYY-MM-DDT00:00:00Z as parameter of Date constructor. For example

const dateTime = new Date('2012-06-08').getTime();
const timestamp = Math.floor(dateTime / 1000);

You can just add a + sign also when declaring a Date object like below

const dateTime = +new Date();
const timestamp = Math.floor(dateTime / 1000);

or for specific date

const dateTime = +new Date('2012-06-08');
const timestamp = Math.floor(dateTime / 1000);

Under the hood the runtime calls valueOf method of the Date object. Then the unary + operator calls toNumber() with that returned value. For detailed explanation please check the following links

title: Helpful Console Logging Tricks tip-number: 50 tip-username: zackhall tip-username-profile: https://twitter.com/zthall tip-tldr: Helpful logging techniques using coercion and conditonal breakpoints.

  • /en/helpful-console-log-hacks/

Using conditional breakpoints to log data

If you wanted to log to the console a value each time a function is called, you can use conditional break points to do this. Open up your dev tools, find the function where you'd like to log data to the console and set a breakpoint with the following condition:

console.log(data.value) && false;

A conditional breakpoint pauses the page thread only if the condition for the breakpoint evaluates to true. So by using a condition like console.log('foo') && false it's guaranteed to evaluate to false since you're putting the literal false in the AND condition. So this will not pause the page thread when it's hit, but it will log data to the console. This can also be used to count how many times a function or callback is called.

Here's how you can set a conditional breakpoint in Edge, Chrome, Firefox and Safari.

Printing a function variable to console

Have you ever logged a function variable to the console and weren't able to just view the function's code? The quickest way to see the function's code is to coerce it to a string using concatenation with an empty string.

console.log(funcVariable + '');

title: DOM event listening made easy tip-number: 51 tip-username: octopitus tip-username-profile: https://github.com/octopitus tip-tldr: An elegant and easy way to handle DOM events

  • /en/DOM-event-listening-made-easy/

Many of us are still doing these things:

  • element.addEventListener('type', obj.method.bind(obj))
  • element.addEventListener('type', function (event) {})
  • element.addEventListener('type', (event) => {})

The above examples all create new anonymous event handlers that can't be removed when no longer needed. This may cause performance problems or unexpected logic bugs, when handlers that you no longer need still get accidentally triggered through unexpected user interactions or event bubbling.

Safer event-handling patterns include the following:

Use a reference:

const handler = function () {
    console.log('Tada!');
};
element.addEventListener('click', handler);
// Later on
element.removeEventListener('click', handler);

Named function that removes itself:

element.addEventListener('click', function click(e) {
    if (someCondition) {
        return e.currentTarget.removeEventListener('click', click);
    }
});

A better approach:

function handleEvent(eventName, { onElement, withCallback, useCapture = false } = {}, thisArg) {
    const element = onElement || document.documentElement;

    function handler(event) {
        if (typeof withCallback === 'function') {
            withCallback.call(thisArg, event);
        }
    }

    handler.destroy = function () {
        return element.removeEventListener(eventName, handler, useCapture);
    };

    element.addEventListener(eventName, handler, useCapture);
    return handler;
}

// Anytime you need
const handleClick = handleEvent('click', {
    onElement: element,
    withCallback: (event) => {
        console.log('Tada!');
    }
});

// And anytime you want to remove it
handleClick.destroy();

title: Return Values with the 'new' Operator tip-number: 52 tip-username: Morklympious tip-username-profile: https://github.com/morklympious tip-tldr: Understand what gets returned when using new vs. not using new.

  • /en/return-values-with-the-new-operator/

You're going to run into some instances where you'll be using new to allocate new objects in JavaScript. It's going to blow your mind unless you read this tip to understand what's happening behind the scenes.

The new operator in JavaScript is an operator that, under reasonable circumstances, returns a new instance of an object. Let's say we have a constructor function:

function Thing() {
    this.one = 1;
    this.two = 2;
}

var myThing = new Thing();

myThing.one; // 1
myThing.two; // 2

Note: this refers to the new object created by new. Otherwise if Thing() is called without new, no object is created, and this is going to point to the global object, which is window. This means that:

  1. You'll suddenly have two new global variables named one and two.
  2. myThing is now undefined, since nothing is returned in Thing().

Now that you get that example, here's where things get a little bit wonky. Let's say I add something to the constructor function, a little SPICE:

function Thing() {
    this.one = 1;
    this.two = 2;

    return 5;
}

var myThing = new Thing();

Now, what does myThing equal? Is it 5? is it an object? Is it my crippled sense of self-worth? The world may never know!

Except the world does know:

myThing.one; // 1
myThing.two; // 2

Interestingly enough, we never actually see the five that we supposedly 'returned' from our constructor. That's weird, isn't it? What are you doing function? WHERE'S THE FIVE? Let's try it with something else.

Let's return a non-primitive type instead, something like an object.

function Thing() {
    this.one = 1;
    this.two = 2;

    return {
        three: 3,
        four: 4
    };
}

var myThing = new Thing();

Let's check it out. A quick console.log reveals all:

console.log(myThing);
/*
  Object {three: 3, four: 4}
  What happened to this.one and this.two!?
  They've been stomped, my friend.
*/

Here's where we learn: When you invoke a function with the new keyword, you can set properties on it using the keyword this (but you probably already knew that). Returning a primitive value from a function you called with the new keyword will not return the value you specified, but instead will return the this instance of the function (the one you put properties on, like this.one = 1;).

However, returning a non-primitive, like an object, array, or function will stomp on the this instance, and return that non-primitive instead, effectively ruining all the hard work you did assigning everything to this.

title: Get File Extension tip-number: 53 tip-username: richzw tip-username-profile: https://github.com/richzw tip-tldr: How to get the file extension more efficiently?

  • /en/get-file-extension/

categories: - en - javascript


Question: How to get the file extension?

var file1 = '50.xsl';
var file2 = '30.doc';
getFileExtension(file1); //returs xsl
getFileExtension(file2); //returs doc

function getFileExtension(filename) {
    /*TODO*/
}

Solution 1: Regular Expression

function getFileExtension1(filename) {
    return /[.]/.exec(filename) ? /[^.]+$/.exec(filename)[0] : undefined;
}

Solution 2: String split method

function getFileExtension2(filename) {
    return filename.split('.').pop();
}

Those two solutions couldnot handle some edge cases, here is another more robust solution.

Solution3: String slice, lastIndexOf methods

function getFileExtension3(filename) {
    return filename.slice(((filename.lastIndexOf('.') - 1) >>> 0) + 2);
}

console.log(getFileExtension3('')); // ''
console.log(getFileExtension3('filename')); // ''
console.log(getFileExtension3('filename.txt')); // 'txt'
console.log(getFileExtension3('.hiddenfile')); // ''
console.log(getFileExtension3('filename.with.many.dots.ext')); // 'ext'

How does it works?

  • String.lastIndexOf() method returns the last occurrence of the specified value ('.' in this case). Returns -1 if the value is not found.
  • The return values of lastIndexOf for parameter 'filename' and '.hiddenfile' are -1 and 0 respectively. Zero-fill right shift operator (>>>) will transform -1 to 4294967295 and -2 to 4294967294, here is one trick to insure the filename unchanged in those edge cases.
  • String.prototype.slice() extracts file extension from the index that was calculated above. If the index is more than the length of the filename, the result is "".

Comparison

Solution Paramters Results
Solution 1: Regular Expression ''
'filename'
'filename.txt'
'.hiddenfile'
'filename.with.many.dots.ext'
undefined
undefined
'txt'
'hiddenfile'
'ext'
Solution 2: String split ''
'filename'
'filename.txt'
'.hiddenfile'
'filename.with.many.dots.ext'
''
'filename'
'txt'
'hiddenfile'
'ext'
Solution 3: String slice, lastIndexOf ''
'filename'
'filename.txt'
'.hiddenfile'
'filename.with.many.dots.ext'
''
''
'txt'
''
'ext'

Live Demo and Performance

Here is the live demo of the above codes.

Here is the performance test of those 3 solutions.

Source

How can I get file extensions with JavaScript

title: How to use optional arguments in functions (with optional callback) tip-number: 54 tip-username: alphashuro tip-username-profile: https://github.com/alphashuro tip-tldr: You can make function arguments and callback optional

  • /en/use-optional-arguments/

categories: - en - javascript


Example function where arguments 2 and 3 are optional

function example(err, optionalA, optionalB, callback) {
    // retrieve arguments as array
    var args = new Array(arguments.length);
    for (var i = 0; i < args.length; ++i) {
        args[i] = arguments[i];
    }

    // first argument is the error object
    // shift() removes the first item from the
    // array and returns it
    err = args.shift();

    // if last argument is a function then its the callback function.
    // pop() removes the last item in the array
    // and returns it
    if (typeof args[args.length - 1] === 'function') {
        callback = args.pop();
    }

    // if args still holds items, these are
    // your optional items which you could
    // retrieve one by one like this:
    if (args.length > 0) optionalA = args.shift();
    else optionalA = null;
    if (args.length > 0) optionalB = args.shift();
    else optionalB = null;

    // continue as usual: check for errors
    if (err) {
        return callback && callback(err);
    }

    // for tutorial purposes, log the optional parameters
    console.log('optionalA:', optionalA);
    console.log('optionalB:', optionalB);
    console.log('callback:', callback);

    /* do your thing */
}

// ES6 with shorter, more terse code
function example(...args) {
    // first argument is the error object
    const err = args.shift();
    // if last argument is a function then its the callback function
    const callback = typeof args[args.length - 1] === 'function' ? args.pop() : null;

    // if args still holds items, these are your optional items which you could retrieve one by one like this:
    const optionalA = args.length > 0 ? args.shift() : null;
    const optionalB = args.length > 0 ? args.shift() : null;
    // ... repeat for more items

    if (err && callback) return callback(err);

    /* do your thing */
}

// invoke example function with and without optional arguments

example(null, 'AA');

example(null, function (err) {
    /* do something */
});

example(null, 'AA', function (err) {});

example(null, 'AAAA', 'BBBB', function (err) {});

How do you determine if optionalA or optionalB is intended?

Design your function to require optionalA in order to accept optionalB

title: Create an easy loop using an array tip-number: 55 tip-username: jamet-julien tip-username-profile: https://github.com/jamet-julien tip-tldr: Sometimes, we need to loop endlessly over an array of items, like a carousel of images or an audio playlist. Here's how to take an array and give it "looping powers”

  • /en/make-easy-loop-on-array/

categories: - en - javascript


Sometimes, we need to loop endlessly over an array of items, like a carousel of images or an audio playlist. Here's how to take an array and give it "looping powers":

var aList = ['A', 'B', 'C', 'D', 'E'];

function make_looper(arr) {
    arr.loop_idx = 0;

    // return current item
    arr.current = function () {
        if (this.loop_idx < 0) {
            // First verification
            this.loop_idx = this.length - 1; // update loop_idx
        }

        if (this.loop_idx >= this.length) {
            // second verification
            this.loop_idx = 0; // update loop_idx
        }

        return arr[this.loop_idx]; //return item
    };

    // increment loop_idx AND return new current
    arr.next = function () {
        this.loop_idx++;
        return this.current();
    };
    // decrement loop_idx AND return new current
    arr.prev = function () {
        this.loop_idx--;
        return this.current();
    };
}

make_looper(aList);

aList.current(); // -> A
aList.next(); // -> B
aList.next(); // -> C
aList.next(); // -> D
aList.next(); // -> E
aList.next(); // -> A
aList.pop(); // -> E
aList.prev(); // -> D
aList.prev(); // -> C
aList.prev(); // -> B
aList.prev(); // -> A
aList.prev(); // -> D

Using the % ( Modulus ) operator is prettier.The modulus return division's rest ( 2 % 5 = 1 and 5 % 5 = 0):

var aList = ['A', 'B', 'C', 'D', 'E'];

function make_looper(arr) {
    arr.loop_idx = 0;

    // return current item
    arr.current = function () {
        this.loop_idx = this.loop_idx % this.length; // no verification !!
        return arr[this.loop_idx];
    };

    // increment loop_idx AND return new current
    arr.next = function () {
        this.loop_idx++;
        return this.current();
    };

    // decrement loop_idx AND return new current
    arr.prev = function () {
        this.loop_idx += this.length - 1;
        return this.current();
    };
}

make_looper(aList);

aList.current(); // -> A
aList.next(); // -> B
aList.next(); // -> C
aList.next(); // -> D
aList.next(); // -> E
aList.next(); // -> A
aList.pop(); // -> E
aList.prev(); // -> D
aList.prev(); // -> C
aList.prev(); // -> B
aList.prev(); // -> A
aList.prev(); // -> D

title: Copy to Clipboard tip-number: 56 tip-username: loverajoel tip-username-profile: https://twitter.com/loverajoel tip-tldr: This week I had to create a common "Copy to Clipboard" button, I've never created one before and I want to share how I made it. tip-writer-support: https://www.coinbase.com/loverajoel

  • /en/copy-to-clipboard/

categories: - en - javascript


This is a simple tip, this week I had to create a common "Copy to Clipboard" button, I've never created one before and I want to share how I made it. It's easy, the bad thing is that we must add an <input/> with the text to be copied to the DOM. Then, we selected the content and execute the copy command with execCommand. execCommand('copy') will copy the actual selected content.

Also, this command that now is supported by all the latest version of browsers, allows us to execute another system commands like copy, cut, paste, and make changes like fonts color, size, and much more.

document.querySelector('#input').select();
document.execCommand('copy');
Playground
JS Bin on jsbin.com<script src="http://static.jsbin.com/js/embed.min.js?3.39.11"></script>

title: Comma operator in JS tip-number: 57 tip-username: bhaskarmelkani tip-username-profile: https://www.twitter.com/bhaskarmelkani tip-tldr: When placed in an expression, it evaluates every expression from left to right and returns the last one.

  • /en/comma-operaton-in-js/

categories: - en - javascript


Apart from being just a delimiter, the comma operator allows you to put multiple statements in a place where one statement is expected. Eg:-

for (var i = 0, j = 0; i < 5; i++, j++, j++) {
    console.log('i:' + i + ', j:' + j);
}

Output:-

i:0, j:0
i:1, j:2
i:2, j:4
i:3, j:6
i:4, j:8

When placed in an expression, it evaluates every expression from left to right and returns the right most expression.

Eg:-

function a() {
    console.log('a');
    return 'a';
}
function b() {
    console.log('b');
    return 'b';
}
function c() {
    console.log('c');
    return 'c';
}

var x = (a(), b(), c());

console.log(x); // Outputs "c"

Output:-

'a';
'b';
'c';

'c';
  • Note: The comma(,) operator has the lowest priority of all javascript operators, so without the parenthesis the expression would become: (x = a()), b(), c();.
Playground
JS Bin on jsbin.com<script src="http://static.jsbin.com/js/embed.min.js?3.39.11"></script>

title: Breaking or continuing loop in functional programming tip-number: 58 tip-username: vamshisuram tip-username-profile: https://github.com/vamshisuram tip-tldr: A common task for us is iterate over a list looking for a value or values, but we can't return from inside a loop so we will have to iterate the whole array, even if the item we search is the first in the list, in this tip we will see how to short circuit with .some and .every.

  • /en/break-continue-loop-functional/

categories: - en - javascript


A common requirement of iteration is cancelation. Using for loops we can break to end iteration early.

const a = [0, 1, 2, 3, 4];
for (var i = 0; i < a.length; i++) {
    if (a[i] === 2) {
        break; // stop the loop
    }
    console.log(a[i]);
}
//> 0, 1

Another common requirement is to close over our variables.

A quick approach is to use .forEach but then we lack the ability to break. In this situation the closest we get is continue functionality through return.

[0, 1, 2, 3, 4].forEach(function (val, i) {
    if (val === 2) {
        // how do we stop?
        return true;
    }
    console.log(val); // your code
});
//> 0, 1, 3, 4

The .some is a method on Array prototype. It tests whether some element in the array passes the test implemented by the provided function. If any value is returning true, then it stops executing. Here is a MDN link for more details.

An example quoted from that link

const isBiggerThan10 = (numb) => numb > 10;

[2, 5, 8, 1, 4].some(isBiggerThan10); // false
[12, 5, 8, 1, 4].some(isBiggerThan10); // true

Using .some we get iteration functionally similar to .forEach but with the ability to break through return instead.

[0, 1, 2, 3, 4].some(function (val, i) {
    if (val === 2) {
        return true;
    }
    console.log(val); // your code
});
//> 0, 1

You keep returning false to make it continue to next item. When you return true, the loop will break and a.some(..) will return true.

// Array contains 2
const isTwoPresent = [0, 1, 2, 3, 4].some(function (val, i) {
    if (val === 2) {
        return true; // break
    }
});
console.log(isTwoPresent);
//> true

Also there is .every, which can be used. We have to return the opposite boolean compared to .some.

Playground
JS Bin on jsbin.com<script src="http://static.jsbin.com/js/embed.min.js?3.39.11"></script>

title: ES6, var vs let tip-number: 59 tip-username: richzw tip-username-profile: https://github.com/richzw tip-tldr: In this tip, I will introduce the block-scope difference between keyword var and let. Should I replace var by let? let's take a look

  • /en/keyword-var-vs-let/

categories: - en - javascript


Overview

  • The scope of a variable defined with var is function scope or declared outside any function, global.
  • The scope of a variable defined with let is block scope.
function varvslet() {
    console.log(i); // i is undefined due to hoisting
    // console.log(j); // ReferenceError: j is not defined

    for (var i = 0; i < 3; i++) {
        console.log(i); // 0, 1, 2
    }

    console.log(i); // 3
    // console.log(j); // ReferenceError: j is not defined

    for (let j = 0; j < 3; j++) {
        console.log(j);
    }

    console.log(i); // 3
    // console.log(j); // ReferenceError: j is not defined
}

Difference Details

  • Variable Hoisting

    let will not hoist to the entire scope of the block they appear in. By contrast, var could hoist as below.

{
    console.log(c); // undefined. Due to hoisting
    var c = 2;
}

{
    console.log(b); // ReferenceError: b is not defined
    let b = 3;
}
  • Closure in Loop

    let in the loop can re-binds it to each iteration of the loop, making sure to re-assign it the value from the end of the previous loop iteration, so it can be used to avoid issue with closures.

for (var i = 0; i < 5; ++i) {
    setTimeout(function () {
        console.log(i); // output '5' 5 times
    }, 100);
}

After replacing var with let

// print 1, 2, 3, 4, 5
for (let i = 0; i < 5; ++i) {
    setTimeout(function () {
        console.log(i); // output 0, 1, 2, 3, 4
    }, 100);
}

Should I replace var with let?

NO, let is the new block scoping var. That statement emphasizes that let should replace var only when var was already signaling block scoping stylistically. Otherwise, leave var alone. let improves scoping options in JS, not replaces. var is still a useful signal for variables that are used throughout the function.

let compatibility

  • In server side, such as Node.js, you can safely use the let statement now.
  • In client side, through a transpiler (like Traceur), you can safely use the let statement. Otherwise, please consider the browser support here

Playground

JS Bin on jsbin.com<script src="http://static.jsbin.com/js/embed.min.js?3.39.11"></script>

More info

title: Three useful hacks tip-number: 60 tip-username: leandrosimoes tip-username-profile: https://github.com/leandrosimoes tip-tldr: Three very useful and syntax sugar hacks to speed up your development.

  • /en/three-useful-hacks/

categories: - en - javascript


Getting array items from behind to front

If you want to get the array items from behind to front, just do this:

var newArray = [1, 2, 3, 4];

console.log(newArray.slice(-1)); // [4]
console.log(newArray.slice(-2)); // [3, 4]
console.log(newArray.slice(-3)); // [2, 3, 4]
console.log(newArray.slice(-4)); // [1, 2, 3, 4]

Short-circuits conditionals

If you have to execute a function just if a condition is true, like this:

if (condition) {
    dosomething();
}

You can use a short-circuit just like this:

condition && dosomething();

Set variable default values using "||"

If you have to set a default value to variables, you can simple do this:

var a;

console.log(a); //undefined

a = a || 'default value';

console.log(a); //default value

a = a || 'new value';

console.log(a); //default value

title: Binding objects to functions tip-number: 61 tip-username: loverajoel tip-username-profile: https://github.com/loverajoel tip-tldr: Understanding how to use Bind method with objects and functions in JavaScript

  • /en/binding-objects-to-functions/

categories: - en - javascript


More than often, we need to bind an object to a function's this object. JS uses the bind method when this is specified explicitly and we need to invoke desired method.

Bind syntax

fun.bind(thisArg[, arg1[, arg2[, ...]]])

Parameters

thisArg

this parameter value to be passed to target function while calling the bound function.

arg1, arg2, ...

Prepended arguments to be passed to the bound function while invoking the target function.

Return value

A copy of the given function along with the specified this value and initial arguments.

Bind method in action in JS

const myCar = {
    brand: 'Ford',
    type: 'Sedan',
    color: 'Red'
};

const getBrand = function () {
    console.log(this.brand);
};

const getType = function () {
    console.log(this.type);
};

const getColor = function () {
    console.log(this.color);
};

getBrand(); // object not bind,undefined

getBrand(myCar); // object not bind,undefined

getType.bind(myCar)(); // Sedan

let boundGetColor = getColor.bind(myCar);
boundGetColor(); // Red

title: Working With Websocket Timeout tip-number: 63 tip-username: loverajoel tip-username-profile: https://github.com/loverajoel tip-tldr: A trick to control the timeout

categories: - en - javascript


In case of established websocket connection, server or firewall could timeout and terminate the connection after a period of inactivity. To deal with this situation, we send periodic message to the server. To control the timeout we will add two functions in our code : one to make sure connection keep alive and another one to cancel the keep alive. Also we need a common timerID variable. Let's have a look on implementation-

var timerID = 0;
function keepAlive() {
    var timeout = 20000;
    if (webSocket.readyState == webSocket.OPEN) {
        webSocket.send('');
    }
    timerId = setTimeout(keepAlive, timeout);
}
function cancelKeepAlive() {
    if (timerId) {
        clearTimeout(timerId);
    }
}

Now as we have both of our desired function for the task, we will place keepAlive() function at the end of onOpen() method of websocket connection and cancelKeepAlive() function at the end of onClose() method of websocket connection.

Yes! We have perfectly implemented hack for websocket timeout problem.

title: 3 Array Hacks tip-number: 64 tip-username: hassanhelfi tip-username-profile: https://twitter.com/hassanhelfi tip-tldr: Arrays are everywhere and with the new spread operators introduced in ECMAScript 6, you can do awesome things with them. In this post I will show you 3 useful tricks you can use when programming.

categories: - en - javascript


Arrays are everywhere in JavaScript and with the new spread operators introduced in ECMAScript 6, you can do awesome things with them. In this post I will show you 3 useful tricks you can use when programming.

1. Iterating through an empty array

JavaScript arrays are sparse in nature in that there are a lot of holes in them. Try creating an array using the Array's constructor and you will see what I mean.

> const arr = new Array(4);
[undefined, undefined, undefined, undefined]

You may find that iterating over a sparse array to apply a certain transformation is hard.

> const arr = new Array(4);
> arr.map((elem, index) => index);
[undefined, undefined, undefined, undefined]

To solve this, you can use Array.apply when creating the array.

> const arr = Array.apply(null, new Array(4));
> arr.map((elem, index) => index);
[0, 1, 2, 3]

2. Passing an empty parameter to a method

If you want to call a method and ignore one of its parameters, then JavaScript will complain if you keep it empty.

> method('parameter1', , 'parameter3');
Uncaught SyntaxError: Unexpected token ,

A workaround that people usually resort to is to pass either null or undefined.

> method('parameter1', null, 'parameter3') // or
> method('parameter1', undefined, 'parameter3');

I personally don't like using null since JavaScript treats it as an object and that's just weird. With the introduction of spread operators in ES6, there is a neater way of passing empty parameters to a method. As previously mentioned, arrays are sparse in nature and so passing empty values to it is totally okay. We'll use this to our advantage.

> method(...['parameter1', , 'parameter3']); // works!

3. Unique array values

I always wonder why the Array constructor does not have a designated method to facilitate the use of unique array values. Spread operators are here for the rescue. Use spread operators with the Set constructor to generate unique array values.

> const arr = [...new Set([1, 2, 3, 3])];
[1, 2, 3]

title: Tapping for quick debugging tip-number: 65 tip-username: loverajoel tip-username-profile: https://twitter.com/loverajoel tip-tldr: This little beastie here is tap. A really useful function for quick-debugging chains of function calls, anonymous functions and, actually, whatever you just want to print. tip-md-link: https://github.com/loverajoel/jstips/blob/master/_posts/en/javascript/2017-03-16-tapping-for-quick-debugging.md

categories: - en - javascript


This little beastie here is tap. A really useful function for quick-debugging chains of function calls, anonymous functions and, actually, whatever you just want to print.

function tap(x) {
    console.log(x);
    return x;
}

Why would you use instead of good old console.log? Let me show you an example:

bank_totals_by_client(bank_info(1, banks), table)
    .filter((c) => c.balance > 25000)
    .sort((c1, c2) => (c1.balance <= c2.balance ? 1 : -1))
    .map((c) => console.log(`${c.id} | ${c.tax_number} (${c.name}) => ${c.balance}`));

Now, suppose you're getting nothing from this chain (possibly an error). Where is it failing? Maybe bank_info isn't returning anything, so we'll tap it:

bank_totals_by_client(tap(bank_info(1, banks)), table);

Depending on our particular implementation, it might print something or not. I'll assume the information that we got from our tapping was correct and therefore, bank_info isn't causing anything.

We must then move on to the next chain, filter.

            .filter(c => tap(c).balance > 25000)

Are we receiving any c's (clients actually)? If so, then bank_totals_by_client works alright. Maybe it's the condition within the filter?

            .filter(c => tap(c.balance > 25000))

Ah! Sweet, we see nothing but false printed, so there's no client with >25000, that's why the function was returning nothing.

(Bonus) A more advanced tap.

function tap(x, fn = (x) => x) {
    console.log(fn(x));
    return x;
}

Now we're talking about a more advanced beast, what if we wanted to perform a certain operation prior to tapping? i.e, we want to access a certain object property, perform a logical operation, etc. with our tapped object? Then we call old good tap with an extra argument, a function to be applied at the moment of tapping.

tap(3, (x) => x + 2) === 3; // prints 5, but expression evaluates to true, why :-)?

title: Recursion, iteration and tail calls in JS tip-number: 67 tip-username: loverajoel tip-username-profile: https://twitter.com/loverajoel tip-tldr: If you've been on the business for some time, you have, most likely, come across the definition of recursion, for which the factorial of a given number n! = n * n - 1 * ... * 1 is a standard example... tip-md-link: https://github.com/loverajoel/jstips/blob/master/_posts/en/javascript/2017-03-29-recursion-iteration-and-tail-calls-in-js.md

categories: - en - javascript


If you've been on the business for some time, you have, most likely, come across the definition of recursion, for which the factorial of a given number n! = n * (n - 1) * ... * 1 is a standard example.

function factorial(n) {
    if (n === 0) {
        return 1;
    }
    return n * factorial(n - 1);
}

The example shown above is but the most naive implementation of the factorial function.

For the sake of completeness, let's look at how this executes for n = 6:

  • factorial(6)
    • 6 * factorial(5)
      • 5 * factorial (4)
        • 4 * factorial(3)
          • 3 * factorial(2)
            • 2 * factorial(1)
              • 1 * factorial(0)
                • 1
              • (resuming previous execution) 1 * 1 = 1
            • (resuming...) 2 * 1 = 2
          • (...) 3 * 2 = 6
        • ... 4 * 6 = 24
      • 5 * 24 = 120
    • 6 * 120 = 720
  • factorial(6) = 720

Now, we must be very cautious as to what's happening so we can understand what is to come next.

When we invoke a function, several things happen at once. The location to which we must return to after calling the function is saved, along with the information of the current frame (i.e, the value of n). Then space is allocated for the new function and a new frame is born.

This goes on and on, we keep stacking these frames and then we unwind that stack, replacing function calls with values returned by them.

Another thing to notice is the shape of the process generated by our function. You might not be surprised if I call this shape recursive. We have, thus, a recursive process.

Let's take a look at a second implementation of this function.

function factorial(n, res) {
    if (n === 0) {
        return res;
    }
    return factorial(n - 1, res * n);
}

We can encapsulate functionality a bit further by defining an inner function.

function factorial(n) {
    function inner_factorial(n, res) {
        if (n === 0) {
            return res;
        }
        return inner_factorial(n - 1, res * n);
    }
    return inner_factorial(n, 1);
}

Let's take a look at how this gets executed:

  • factorial(6)
    • inner anonymous function (iaf) gets called with (n = 6, res = 1)
      • iaf(5, 1 * 6)
        • iaf(4, 6 * 5)
          • iaf(3, 30 * 4)
            • iaf(2, 120 * 3)
              • iaf(1, 360 * 2)
                • iaf(0, 720)
                  • 720
                • 720
              • 720
            • 720
          • 720
        • 720
      • 720
    • iaf (6, 1) = 720
  • factorial(6) = 720

You might notice that we didn't need to perform any calculation after unwinding the stack. We just returned a value. But, according to our rules, we had to save the state as a stack frame, even if it weren't of any use later in the chain.

Our rules, however, are not applied to every language out there. In fact, in Scheme it's mandatory for such chains to be optimized with tail call optimization. This ensures that our stack is not filled with unnecessary frames. Our previous calculation would look, thus, this way:

  • factorial(6)
  • iaf(6, 1)
  • iaf(5, 6)
  • iaf(4, 30)
  • iaf(3, 120)
  • iaf(2, 360)
  • iaf(1, 720)
  • iaf(0, 720)
  • 720

Which in turns, looks an awfully lot like

res = 1;
n = 6;

while (n > 1) {
    res = res * n;
    n--;
}

This means, we actually have an iterative process, even if we're using recursion. How cool is that?

The good news is, this is a feature in ES6. As long as your recursive call is in tail position and your function has strict mode, tail call optimization will kick in and save you from having a maximum stack size exceeded error.

UPDATE Dec 1, 2017: The only major browser with tail call optimization is Safari.1 V8 has an implentation2 but has not shipped it yet3 for the reasons listed.

1: https://kangax.github.io/compat-table/es6/#test-proper_tail_calls_(tail_call_optimisation)

2: https://bugs.chromium.org/p/v8/issues/detail?id=4698

3: https://v8project.blogspot.com/2016/04/es6-es7-and-beyond.html

title: Why you should use Object.is() in equality comparison tip-number: 68 tip-username: TarekAlQaddy tip-username-profile: https://github.com/TarekAlQaddy tip-tldr: A good solution for the looseness of equality comparisons in javascript

categories: - en - javascript


We all know that JavaScript is loosely typed and in some cases it fall behind specially when it comes to quality comparison with '==', comparing with '==' gives unexpected results due to whats called coercion or casting "converting one of the 2 operands to the other's type then compare".

0 == ' '; //true
(null == undefined[1]) == //true
    true; //true

So they provided us with the triple equal operator '===' which is more strict and does not coerce operands, However comparing with '===' is not the best solution you can get:

NaN === NaN; //false

The great news that in ES6 there is the new 'Object.is()' which is better and more precise it has the same features as '===' and moreover it behaves well in some special cases:

Object.is(0, ' '); //false
Object.is(null, undefined); //false
Object.is([1], true); //false
Object.is(NaN, NaN); //true

Mozilla team doesn't think that Object.is is "stricter" than '===', they say that we should think of how this method deal with NaN, -0 and +0 but overall I think it is now a good practice in real applications.

Now this table illustrates..

differences of operators in equality comparisons javascript

References:

Equality comparisons and sameness

title: Picking and rejecting object properties tip-number: 70 tip-username: loverajoel tip-username-profile: https://github.com/loverajoel tip-tldr: Sometimes we need to whitelist certain attributes from an object, say we've got an array representation of a database table and we need to select just a few fields for some function.

categories: - en - javascript


Sometimes we need to whitelist certain attributes from an object, say we've got an array representation of a database table and we need to select just a few fields for some function:

function pick(obj, keys) {
    return keys.map((k) => (k in obj ? { [k]: obj[k] } : {})).reduce((res, o) => Object.assign(res, o), {});
}

const row = {
    'accounts.id': 1,
    'client.name': 'John Doe',
    'bank.code': 'MDAKW213'
};

const table = [row, { 'accounts.id': 3, 'client.name': 'Steve Doe', 'bank.code': 'STV12JB' }];

pick(row, ['client.name']); // Get client name

table.map((row) => pick(row, ['client.name'])); // Get a list of client names

There's a bit of skulduggery going on in pick. First, we map a function over the keys that will return, each time, an object with only the attribute pointed by the current key (or an empty object if there's no such attribute in the object). Then, we reduce this collection of single-attribute objects by merging the objects.

But what if we want to reject the attributes? Well, the function changes a bit

function reject(obj, keys) {
    return Object.keys(obj)
        .filter((k) => !keys.includes(k))
        .map((k) => Object.assign({}, { [k]: obj[k] }))
        .reduce((res, o) => Object.assign(res, o), {});
}

// or, reusing pick
function reject(obj, keys) {
    const vkeys = Object.keys(obj).filter((k) => !keys.includes(k));
    return pick(obj, vkeys);
}

reject({ a: 2, b: 3, c: 4 }, ['a', 'b']); // => {c: 4}

title: Protocols for the Brave tip-number: 73 tip-username: loverajoel tip-username-profile: https://github.com/loverajoel tip-tldr: You might have heard about the old ways gaining hype recently, and we don't mean praying to the gods of the north. Today we're introducing a feature found in Clojure which allows you to define interfaces for your classes.

categories: - en - javascript


You might have heard about the old ways gaining hype recently, and we don't mean praying to the gods of the north.

Functional programming is the rediscovered toy which is bringing some sanity to the world of mutable state and global bindings.

Today we're introducing a feature found in Clojure which allows you to define interfaces for your classes. Let's look at one-off implementation:

const protocols = (...ps) => ps.reduce((c, p) => p(c), Object);

const Mappable = (klass) => {
    return class extends klass {
        map() {
            throw 'Not implemented';
        }
    };
};

const Foldable = (klass) => {
    return class extends klass {
        fold() {
            throw 'Not implemented';
        }
    };
};

class NaturalNumbers extends protocols(Mappable, Foldable) {
    constructor() {
        super();
        this.elements = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    }

    map(f) {
        return this.elements.map(f);
    }

    fold(f) {
        return this.elements.reduce(f, this.elements, 0);
    }
}

Yes, we're building a chain of class inheritance up there with that reduce boy. It's pretty cool. We're doing it dynamically! You see, each protocol receives a base class (Object) and extends it somehow returning the new class. The idea is similar to that of interfaces.

We supply method signatures for the protocol and make sure we provide implementations for it on our base classes.

What's so cool about it? We get to write things like these:

const map = (f) => (o) => o.map(f);
const fold = (f) => (o) => o.fold(f);
const compose = (...fns) => fns.reduce((acc, f) => (x) => acc(f(x)), id);

Ok, maybe we could have written those two functions without the above fuzz but, now that we know NaturalNumbers are Mappable, we can call map on them and trust it will return the right result. Furthermore, with our third function, we can compose any number of operations defined in protocols cleanly:

const plus1 = (x) => x + 1;
const div5 = (x) => x / 5;
const plus_then_div = compose(map(div5), map(plus1));
console.log(plus_then_div(new NaturalNumbers()));
// => [ 0.4, 0.6, 0.8, 1, 1.2, 1.4, 1.6, 1.8, 2 ]

More important, if we know that an object of ours is Mappable, we know map will work on it. Protocols gives us an idea of what we can do with an object and help us abstract common operations between data types, thus reducing the overhead of dealing with a hundred functions.

What is easier? To have a hundred functions for every different object or ten functions that work on a hundred objects?

title: Improving your Async functions with WebWorkers tip-number: 74 tip-username: loverajoel tip-username-profile: https://github.com/loverajoel tip-tldr: JS runs in a single thread in the browser, this is the truth. In this tip I'll show you how to unleash the full power of asynchronous processing with Web Workers.

categories: - en - javascript


JS shall have but one Thread (in the browser at least)

-- Thus spoke the master programmer.

JS runs in a single thread in the browser, this is the truth.

Somewhere in its own universe, there exists a Queue which holds messages and functions associated with them.

Every time an event (i.e, a user clicks a button) is registered, there's a runtime check to see whether there's any listener attached to that event. If there's one, it will enqueue the message. Otherwise, it will be lost forever.

Now, our event loop processes one message at a time, meaning that if you do some CPU intensive operation (i.e, number crunching) this will indeed 'block' the one Thread, rendering our application useless.

This is true even for async functions, which will be queued as soon as invoked and executed as soon as possible (immediately given the queue is empty).

I/O such as requests to external resources are non-blocking though, so you can request a file as large as you want without fear. The associated callback, however, will show the same characteristics of an async function.

Strategies for processing lots of data vary a lot. You could partition data and set timeouts for processing bits of it a time for example. But to unleash the full power of asynchronous processing, you should use Web Workers.

To do so, you separate the processing part in a different file (possibly 'my_worker.js'), create a worker with newWorker = new Worker('my_worker.js'); and offload the processing to it.

// my_worker.js
const do_a_lot_of_processing = (data) => {
    ....
}

onmessage = (e) => {
    postMessage(do_a_lot_of_processing(e.data));
}

// main.js
const myWorker = new Worker('my_worker.js');

async function get_useful_data() {
    const raw_data = await request(some_url);
    myWorker.postmessage(raw_data);
}

const show_data => (e) {
    const data = e.data;
    ...
}

myWorker.onmessage(show_data);
get_useful_data();

Your mileage may vary of course, and there are many abstractions that can be built upon this model.

title: Closures inside loops tip-number: 76 tip-username: loverajoel tip-username-profile: https://github.com/loverajoel tip-tldr: Closure in a loop is an interesting topic and this is the tip to be a master of it

categories: - en - javascript


If you ever come across the likes of

var funcs = [];
for (var i = 0; i < 3; i++) {
    funcs[i] = function () {
        console.log('i value is ' + i);
    };
}

for (var k = 0; k < 3; k++) {
    funcs[k]();
}

You will notice that the expected output of

i value is 0
i value is 1
i value is 2

Doesn't match the actual output which will resemble

i value is 3
i value is 3
i value is 3

This is because of how the capturing mechanism of closures work and how i is represented internally.

To solve this situation you can do as follows:

for (var i = 0; i < 3; i++) {
    funcs[i] = (function (value) {
        console.log('i value is ' + i);
    })(i);
}

Which effectively copies i by value by handing it to our closure or

for (let i = 0; i < 3; i++) {
    funcs[i] = function () {
        console.log('i value is ' + i);
    };
}

Where let scopes the variable to our for loop and produces a new value each iteration, thus i will be bound to different values on our closures as expected.

title: Immutable structures and cloning tip-number: 78 tip-username: loverajoel tip-username-profile: https://github.com/loverajoel tip-tldr: Object cloning is a tricky, full of edge-cases, endeavor. The reason is simple enough. Objects maintain internal state, and that is much abused. There are countless techniques, or better phrased, countless derivations of the same technique.

categories: - en - javascript


Object cloning is a tricky, full of edge-cases, endeavor. The reason is simple enough. Objects maintain internal state, and that is much abused. There are countless techniques, or better phrased, countless derivations of the same technique.

Cloning an object is an indicator that your application is growing, and that you've got a complex object which you'd want to treat as an immutable value, i.e operate on it while maintaining a previous state.

If the object is in your control, you're lucky. A bit of refactoring here and there might lead you to a point where you avoid the problem entirely by rethinking your object's structure and behavior.

With the rediscovering of functional programming techniques, a myriad of debates have been held about immutable structures and how they offer exactly what you seek for. Mutable state is the root of all evil, some might argue.

We encourage to reach ImmutableJS by Facebook which provides a nice set of immutable structures free for use. By rethinking your object's inner workings and separating state from behavior, making each function consume a state to produce a new one - much like the Haskell's State monad - you will reduce many nuisances.

If the object is outside your control, you're partly out of luck. This can be circumvented by creating convoluted computations where you solve for yourself circular references and reach enlightenment. However, as you're using external objects anyways, and they must come, as their name says, from external sources, then you might be more comfortable handling the matter to yet another external library and focus on what matters the most, i.e, your application itself.

One such library is pvorb/clone, which has a very simple API. To clone an object you only have to

var clone = require('clone');

var a = { foo: { bar: 'baz' } };
var b = clone(a);
a.foo.bar = 'foo';
console.log(a); // {foo: {bar: 'foo'}}
console.log(b); // {foo: {bar: 'baz'}}

There are, of course, many more libraries that allow you to do the same such as Ramda, lodash.clonedeep and lodash.clone.

As an end note, if you are serious about dealing with immutable structures, you might want to check ClojureScript or (for those that feel that Haskell's worth a shot) PureScript.

We neither encourage, nor condemn, the use of self made cloning mechanisms. Only noting that considerable work has been done on the area and that you'd probably be better of reusing than reinventing the wheel.

title: Looping over arrays tip-number: 79 tip-username: loverajoel tip-username-profile: https://github.com/loverajoel tip-tldr: There's a few methods for looping over arrays in Javascript. We'll start with the classical ones and move towards additions made to the standard.

categories: - en - javascript


Looping over arrays

There's a few methods for looping over arrays in Javascript. We'll start with the classical ones and move towards additions made to the standard.

while

let index = 0;
const array = [1, 2, 3, 4, 5, 6];

while (index < array.length) {
    console.log(array[index]);
    index++;
}

for (classical)

const array = [1, 2, 3, 4, 5, 6];
for (let index = 0; index < array.length; index++) {
    console.log(array[index]);
}

forEach

const array = [1, 2, 3, 4, 5, 6];

array.forEach(function (current_value, index, array) {
    console.log(`At index ${index} in array ${array} the value is ${current_value}`);
});
// => undefined

map

The last construct was useful, however, it doesn't return a new array which might be undesirable for your specific case. map solves this by applying a function over every element and then returning the new array.

const array = [1, 2, 3, 4, 5, 6];
const square = (x) => Math.pow(x, 2);
const squares = array.map(square);
console.log(`Original array: ${array}`);
console.log(`Squared array: ${squares}`);

The full signature for map is .map(current_value, index, array).

reduce

From MDN:

The reduce() method applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value.

const array = [1, 2, 3, 4, 5, 6];
const sum = (x, y) => x + y;
const array_sum = array.reduce(sum, 0);
console.log(`The sum of array: ${array} is ${array_sum}`);

filter

Filters elements on an array based on a boolean function.

const array = [1, 2, 3, 4, 5, 6];
const even = (x) => x % 2 === 0;
const even_array = array.filter(even);
console.log(`Even numbers in array ${array}: ${even_array}`);

every

Got an array and want to test if a given condition is met in every element?

const array = [1, 2, 3, 4, 5, 6];
const under_seven = (x) => x < 7;

if (array.every(under_seven)) {
    console.log('Every element in the array is less than 7');
} else {
    console.log('At least one element in the array was bigger than 7');
}

some

Test if at least one element matches our boolean function.

const array = [1, 2, 3, 9, 5, 6, 4];
const over_seven = (x) => x > 7;

if (array.some(over_seven)) {
    console.log('At least one element bigger than 7 was found');
} else {
    console.log('No element bigger than 7 was found');
}

title: Hash maps without side effects tip-number: 73 tip-username: bhaskarmelkani tip-username-profile: https://www.twitter.com/bhaskarmelkani tip-tldr: Create hash maps(without side effects) using Object.create(null).

categories: - en - javascript


Hash maps without side effects

When you want to use javascript object as a hash map(purely for storing data), you might want to create it as follows.

const map = Object.create(null);

When creating a map using object literal(const map = {}), the map inherits properties from Object by default. It is equivalent to Object.create(Object.prototype).

But by doing Object.create(null), we explicitly specify null as its prototype. So it have absolutely no properties, not even constructor, toString, hasOwnProperty, etc. so you're free to use those keys in your data structure if you need to.

Rationale:

const dirtyMap = {};
const cleanMap = Object.create(null);

dirtyMap.constructor    // function Object() { [native code] }

cleanMap.constructor    // undefined

// Iterating maps

const key;
for(key in dirtyMap){
  if (dirtyMap.hasOwnProperty(key)) {   // Check to avoid iterating over inherited properties.
    console.log(key + " -> " + dirtyMap[key]);
  }
}

for(key in cleanMap){
  console.log(key + " -> " + cleanMap[key]);    // No need to add extra checks, as the object will always be clean
}

Notes:

title: Creating immutable objects in native JavaScript tip-number: 74 tip-username: loverajoel tip-username-profile: https://www.twitter.com/loverajoel tip-tldr: With the latest versions of JavaScript it's possible to create immutable objects. I'll walk you through how to do it in three different ways.

categories: - en - javascript


Creating immutable objects in native JavaScript

Javascript it's a flexible language, you can redefine anything. But when projects get complex we find problems with mutable data structures. With the latest versions of JavaScript this situation changed. Now it's possible to create immutable objects. I'll walk you through how to do it in three different ways.

Wait, what means immutable?

Immutability in object means we don't want our objects to change in any ways once we create them i.e make them read-only type.

Let's suppose we need to define a car Object and use its properties to perform operations throughout our entire project. We can't allow modifying by mistake any data.

const myTesla = {
	maxSpeed: 250,
	batteryLife: 300,
	weight: 023
};

This method prevents the addition of new properties to our existing object. preventExtensions() is a irreversible operation. We can never add extra properties to the object again.

Object.isExtensible(myTesla); // true
Object.preventExtensions(myTesla);
Object.isExtensible(myTesla); // false
myTesla.color = 'blue';
console.log(myTesla.color) // undefined

It prevents additions or deletion of properties. seal() also prevents the modification of property descriptors.

Object.isSealed(myTesla); // false
Object.seal(myTesla);
Object.isSealed(myTesla); // true

myTesla.color = 'blue';
console.log(myTesla.color); // undefined

delete myTesla.batteryLife; // false
console.log(myTesla.batteryLife); // 300

Object.defineProperty(myTesla, 'batteryLife'); // TypeError: Cannot redefine property: batteryLife

It does the same that Object.seal() plus it makes the properties non-writable.

Object.isFrozen(myTesla); // false
Object.freeze(myTesla);
Object.isFrozen(myTesla); // true

myTesla.color = 'blue';
console.log(myTesla.color); // undefined

delete myTesla.batteryLife;
console.log(myTesla.batteryLife); // 300

Object.defineProperty(myTesla, 'batteryLife'); // TypeError: Cannot redefine property: batteryLife

myTesla.batteryLife = 400;
console.log(myTesla.batteryLife); // 300

Extra

Use strict mode if you want to throw an error when trying to modify an immutable object.

title: What is Functional Inheritance? tip-number: 75 tip-username: loverajoel tip-username-profile: https://www.twitter.com/loverajoel tip-tldr: Functional inheritance is the process of inheriting features by applying an augmenting function to an object instance.

categories: - en - javascript


Functional inheritance is the process of inheriting features by applying an augmenting function to an object instance. The function supplies a closure scope which you can use to keep some data private. The augmenting function uses dynamic object extension to extend the object instance with new properties and methods.

Functional mixins are composable factory functions that add properties and behaviors to objects like stations in an assembly line.

// Base object constructor function
function Animal(data) {
    var that = {}; // Create an empty object
    that.name = data.name; // Add it a "name" property
    return that; // Return the object
}

// Create achild object, inheriting from the base Animal
function Cat(data) {
    // Create the Animal object
    var that = Animal(data);
    // Extend base object
    that.sayHello = function () {
        return "Hello, I'm " + that.name;
    };
    return that;
}

// Usage
var myCat = Cat({ name: 'Rufi' });
console.log(myCat.sayHello());
// Output: "Hello, I'm Rufi"

title: What is a currying function? tip-number: 75 tip-username: loverajoel tip-username-profile: https://www.twitter.com/loverajoel tip-tldr: A currying function is a function that takes multiple arguments and turns it into a sequence of functions having only one argument at a time.

categories: - en - javascript


A currying function is a function that takes multiple arguments and turns it into a sequence of functions having only one argument at a time.

In this way, an n-ary function becomes a unary function, and the last function returns the result of all the arguments together in a function.

// Normal definition
function multiply(a, b, c) {
    return a * b * c;
}
console.log(multiply(1, 2, 3));
// Output: 6

// Simple curry function definition
function multiply(a) {
    return (b) => {
        return (c) => {
            return a * b * c;
        };
    };
}
console.log(multiply(1)(2)(3));
// Output: 6

Further readings:

title: What is the Temporal Dead Zone? tip-number: 76 tip-username: loverajoel tip-username-profile: https://www.twitter.com/loverajoel tip-tldr: Temporal Dead Zone is a JavaScript behavior while using variables declared using let and const keywords.

categories: - en - javascript


Temporal Dead Zone is a JavaScript behavior while using variables declared using let and const keywords. Since the keywords are block-scoped, the variables declared these keywords could not be accessed before the declaration, and then you will have to witness where variables will be said to be undefined.

function myFunc() {
    console.log(greeting);
    var greeting = 'Hello World!';
}
myFunc(); // Output: undefined

function myFunc() {
    console.log(greeting);
    let greeting = 'Hello World!';
}
myFunc(); // Output: ReferenceError: greeting is not defined

function myFunc() {
    console.log(greeting);
    const greeting = 'Hello World!';
}
myFunc(); // Output: ReferenceError: greeting is not defined

title: What is the difference between Target and currentTarget in the event context? tip-number: 77 tip-username: loverajoel tip-username-profile: https://www.twitter.com/loverajoel tip-tldr: target refers to the element that triggers an event. currentTarget to the element that the event listener is listening on.

categories: - en - javascript


target refers to the DOM element that triggers an event. Otherwise, currentTarget refers to the DOM element that the event listener is listening on.

<ul class="todo-list">
    <li class="item">Walk your dog</li>
</ul>
const list = document.querySelector('.todo-list');

list.addEventListener('click', (e) => {
    console.log(e.target);
    // Output: <li class="item">Walk your dog</li>
    console.log(e.currentTarget);
    // Output: <ul class="todo-list"></ul>
});

title: What is a spread operator? tip-number: 78 tip-username: loverajoel tip-username-profile: https://www.twitter.com/loverajoel tip-tldr: The spread operator is a useful syntax for manipulating arrays and objects.

categories: - en - javascript


The spread operator in JavaScript is a useful syntax for adding elements to an array, combining arrays into one larger one, spreading an array inside the arguments of a function, and more.

// Concatenating arrays and objects
let arr1 = [1, 2, 3];
let arr2 = [4, 5];
let newArray = [...arr1, ...arr2];
console.log(newArray);
// Output: [ 1, 2, 3, 4, 5 ]

// Copying array elements
let arr = ['a', 'b', 'c'];
let newArray = [...arr];
console.log(newArray);
// Output: ["a", "b", "c"]

// Expanding arrays
let arr = ['a', 'b'];
let newArray = [...arr, 'c', 'd'];
console.log(newArray);
// Output: ["a", "b", "c", "d"]

// Merging objects
const userBasic = {
    name: 'Jen',
    age: 22
};
const userMoreInfo = {
    country: 'Argentina',
    city: 'Córdoba'
};
const user = { ...userBasic, ...userMoreInfo };
// Output: {  name: "Jen",  age: 22, country: "Argentina", city: "Córdoba" }

title: What is a void operator? tip-number: 79 tip-username: loverajoel tip-username-profile: https://www.twitter.com/loverajoel tip-tldr: The void operator returns an undefined value from an evaluated expression

categories: - en - javascript


The void operator returns an undefined value from an evaluated expression, or in other words; the void operator specifies an expression to be evaluated without returning a value. It is commonly used in client-side JavaScript, where the browser should not display the value.

function getYear() {
    return 2020;
}

console.log(getYear());
// Output: 2020

console.log(void getYear());
// Output: undefined

// Useful use case
button.onclick = () => void getYear();

layout: post

title: What is the promise executor? tip-number: 80 tip-username: loverajoel tip-username-profile: https://www.twitter.com/loverajoel tip-tldr: The method received as an argument for the promise.

categories: - en - javascript

All Promise instances accept a method as an argument called the executor. This executor takes two methods as arguments: resolve and reject. Within the executor, if resolve is called, the Promise instance becomes fulfilled. If an exception is thrown, reject is called instead, and the Promise instance becomes rejected.

const executor = (resolve, reject) => {
    setTimeout(() => resolve("I'm done"), 1000);
};

new Promise(executor).then((result) => {
    console.log(result);
    // Output after 1000ms: I'm done
});

layout: post

title: What is the JavaScript ternary operator? tip-number: 81 tip-username: loverajoel tip-username-profile: https://www.twitter.com/loverajoel tip-tldr: The ternary operator is a shortcut for the if statement.

categories: - en - javascript

The ternary operator is a shortcut for the if statement. It consists of three operands; a question mark, a condition, and an expression to execute if the condition is true, followed by a colon and another expression to execute if it's false.

let age = 26;

// condition ? expression if true : expression if false
let drink = age >= 21 ? 'Beer' : 'Juice';

console.log(drink); // "Beer"

// Equivalent to:
let drink;
if (age >= 21) {
    drink = 'Beer';
} else {
    drink = 'Juice';
}

console.log(drink); // "Beer"

About the JavaScript reference

The JavaScript reference serves as a repository of facts about the JavaScript language. The entire language is described here in detail. As you write JavaScript code, you'll refer to these pages often (thus the title "JavaScript reference"). If you're learning JavaScript, or need help understanding some of its capabilities or features, check out the JavaScript guide.

The JavaScript language is intended to be used within some larger environment, be it a browser, server-side scripts, or similar. For the most part, this reference attempts to be environment-agnostic and does not target a web browser environment.

Where to find JavaScript information

JavaScript documentation of core language features (pure ECMAScript, for the most part) includes the following:

If you are new to JavaScript, start with the guide. Once you have a firm grasp of the fundamentals, you can use the reference to get more details on individual objects and language constructs.

Structure of the reference

In the JavaScript reference you can find the following chapters:

Standard built-in objects
This chapter documents all the JavaScript standard built-in objects, along with their methods and properties.

Statements and declarations
JavaScript applications consist of statements with an appropriate syntax. A single statement may span multiple lines. Multiple statements may occur on a single line if each statement is separated by a semicolon. This isn't a keyword, but a group of keywords.

Expressions and operators
This chapter documents all the JavaScript language operators, expressions and keywords.

Functions
Chapter about JavaScript functions.

Classes
Chapter about JavaScript classes introduced in ECMAScript 2015.

Errors
Chapter about specific errors, exceptions and warnings thrown by JavaScript.

New in JavaScript
Chapter about JavaScript version history.

More reference pages

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

Math.abs()

The Math.abs() function returns the absolute value of a number. That is, it returns x if x is positive or zero, and the negation of x if x is negative.

Syntax

Math.abs(x)

Parameters

x
A number.

Return value

The absolute value of the given number.

Description

Because abs() is a static method of Math, you always use it as Math.abs(), rather than as a method of a Math object you created (Math is not a constructor).

Examples

Behavior of Math.abs()

Passing an empty object, an array with more than one member, a non-numeric string or undefined/empty variable returns NaN. Passing null, an empty string or an empty array returns 0.

Math.abs('-1');     // 1
Math.abs(-2);       // 2
Math.abs(null);     // 0
Math.abs('');       // 0
Math.abs([]);       // 0
Math.abs([2]);      // 2
Math.abs([1,2]);    // NaN
Math.abs({});       // NaN
Math.abs('string'); // NaN
Math.abs();         // NaN

Specifications

Specification
ECMAScript (ECMA-262)

The definition of 'Math.abs' in that specification.

abs

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/Global_Objects/Math/abs

Math.acos()

The Math.acos() function returns the arccosine (in radians) of a number, that is

x ∈ [ − 1; 1], Math.acos(``x``) = arccos (x) = the unique y ∈ [0; π] such that cos (y) = x

Syntax

Math.acos(x)

Parameters

x
A number representing a cosine, where x is between -1 and 1.

Return value

The arccosine (angle in radians) of the given number if it's between -1 and 1; otherwise, NaN.

Description

The Math.acos() method returns a numeric value between 0 and π radians for x between -1 and 1. If the value of x is outside this range, it returns NaN.

Because acos() is a static method of Math, you always use it as Math.acos(), rather than as a method of a Math object you created (Math is not a constructor).

Examples

Using Math.acos()

Math.acos(-2);  // NaN
Math.acos(-1);  // 3.141592653589793
Math.acos(0);   // 1.5707963267948966
Math.acos(0.5); // 1.0471975511965979
Math.acos(1);   // 0
Math.acos(2);   // NaN

For values less than -1 or greater than 1, Math.acos() returns NaN.

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-math.acos

acos

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/Global_Objects/Math/acos

Math.acosh()

The Math.acosh() function returns the hyperbolic arc-cosine of a number, that is

x ≥ 1, Math.acosh(``x``) = arcosh (x) = the unique y ≥ 0 such that cosh (y) = x

Syntax

Math.acosh(x)

Parameters

x
A number.

Return value

The hyperbolic arc-cosine of the given number. If the number is less than 1, NaN.

Description

Because acosh() is a static method of Math, you always use it as Math.acosh(), rather than as a method of a Math object you created (Math is no constructor).

Examples

Using Math.acosh()

Math.acosh(-1);  // NaN
Math.acosh(0);   // NaN
Math.acosh(0.5); // NaN
Math.acosh(1);   // 0
Math.acosh(2);   // 1.3169578969248166

For values less than 1 Math.acosh() returns NaN.

Polyfill

For all x ≥ 1, we have $\operatorname{arcosh}(x) = \ln\left( {x + \sqrt{x^{2} - 1}} \right)$ and so this can be emulated with the following function:

Math.acosh = Math.acosh || function(x) {
  return Math.log(x + Math.sqrt(x * x - 1));
};

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-math.acosh

acosh

38

12

25

No

25

8

38

38

25

25

8

3.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/Global_Objects/Math/acosh

Atomics.add()

The static Atomics``.add() method adds 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.add(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 add a value to.

value
The number to add.

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.

Examples

Using add()

const sab = new SharedArrayBuffer(1024);
const ta = new Uint8Array(sab);

Atomics.add(ta, 0, 12); // returns 0, the old value
Atomics.load(ta, 0); // 12

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-atomics.add

add

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/add

Addition (+)

The addition operator (+) produces the sum of numeric operands or string concatenation.

Syntax

Operator: x + y

Examples

Numeric addition

// Number + Number -> addition
1 + 2 // 3

// Boolean + Number -> addition
true + 1 // 2

// Boolean + Boolean -> addition
false + false // 0

String concatenation

// String + String -> concatenation
'foo' + 'bar' // "foobar"

// Number + String -> concatenation
5 + 'foo' // "5foo"

// String + Boolean -> concatenation
'foo' + false // "foofalse"

Specifications

Specification
ECMAScript (ECMA-262)

The definition of 'Addition operator' in that specification.

Addition

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/Operators/Addition

AggregateError

The AggregateError object represents an error when several errors need to be wrapped in a single error. It is thrown when multiple errors need to be reported by an operation, for example by Promise.any(), when all promises passed to it reject.

Constructor

AggregateError()
Creates a new AggregateError object.

Instance properties

AggregateError.prototype.message
Error message, defaults to "".

AggregateError.prototype.name
Error name, defaults to AggregateError.

Examples

Catching an AggregateError

Promise.any([
  Promise.reject(new Error("some error")),
]).catch(e => {
  console.log(e instanceof AggregateError); // true
  console.log(e.message);                   // "All Promises rejected"
  console.log(e.name);                      // "AggregateError"
  console.log(e.errors);                    // [ Error: "some error" ]
});

Creating an AggregateError

try {
  throw new AggregateError([
    new Error("some error"),
  ], 'Hello');
} catch (e) {
  console.log(e instanceof AggregateError); // true
  console.log(e.message);                   // "Hello"
  console.log(e.name);                      // "AggregateError"
  console.log(e.errors);                    // [ Error: "some error" ]
}

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-aggregate-error-objects

AggregateError

85

85

79

No

No

14

85

85

79

No

14

No

AggregateError

85

85

79

No

No

14

85

85

79

No

14

No

See also

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

Promise.all()

The Promise.all() method takes an iterable of promises as an input, and returns a single Promise that resolves to an array of the results of the input promises. This returned promise will resolve when all of the input's promises have resolved, or if the input iterable contains no promises. It rejects immediately upon any of the input promises rejecting or non-promises throwing an error, and will reject with this first rejection message / error.

Syntax

Promise.all(iterable);

Parameters

iterable
An iterable object such as an Array.

Return value

  • An already resolved Promise if the iterable passed is empty.
  • An asynchronously resolved Promise if the iterable passed contains no promises. Note, Google Chrome 58 returns an already resolved promise in this case.
  • A pending Promise in all other cases. This returned promise is then resolved/rejected asynchronously (as soon as the stack is empty) when all the promises in the given iterable have resolved, or if any of the promises reject. See the example about "Asynchronicity or synchronicity of Promise.all" below. Returned values will be in order of the Promises passed, regardless of completion order.

Description

This method can be useful for aggregating the results of multiple promises. It is typically used when there are multiple related asynchronous tasks that the overall code relies on to work successfully — all of whom we want to fulfill before the code execution continues.

Promise.all() will reject immediately upon any of the input promises rejecting. In comparison, the promise returned by Promise.allSettled() will wait for all input promises to complete, regardless of whether or not one rejects. Consequently, it will always return the final result of every promise and function from the input iterable.

Fulfillment

The returned promise is fulfilled with an array containing all the resolved values (including non-promise values) in the iterable passed as the argument.

  • If an empty iterable is passed, then the promise returned by this method is fulfilled synchronously. The resolved value is an empty array.
  • If a nonempty iterable is passed, and all of the promises fulfill, or are not promises, then the promise returned by this method is fulfilled asynchronously.

Rejection

If any of the passed-in promises reject, Promise.all asynchronously rejects with the value of the promise that rejected, whether or not the other promises have resolved.

Examples

Using Promise.all

Promise.all waits for all fulfillments (or the first rejection).

var p1 = Promise.resolve(3);
var p2 = 1337;
var p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("foo");
  }, 100);
});

Promise.all([p1, p2, p3]).then(values => {
  console.log(values); // [3, 1337, "foo"]
});

If the iterable contains non-promise values, they will be ignored, but still counted in the returned promise array value (if the promise is fulfilled):

// this will be counted as if the iterable passed is empty, so it gets fulfilled
var p = Promise.all([1,2,3]);
// this will be counted as if the iterable passed contains only the resolved promise with value "444", so it gets fulfilled
var p2 = Promise.all([1,2,3, Promise.resolve(444)]);
// this will be counted as if the iterable passed contains only the rejected promise with value "555", so it gets rejected
var p3 = Promise.all([1,2,3, Promise.reject(555)]);

// using setTimeout we can execute code after the stack is empty
setTimeout(function() {
    console.log(p);
    console.log(p2);
    console.log(p3);
});

// logs
// Promise { <state>: "fulfilled", <value>: Array[3] }
// Promise { <state>: "fulfilled", <value>: Array[4] }
// Promise { <state>: "rejected", <reason>: 555 }

Asynchronicity or synchronicity of Promise.all

This following example demonstrates the asynchronicity (or synchronicity, if the iterable passed is empty) of Promise.all:

// we are passing as argument an array of promises that are already resolved,
// to trigger Promise.all as soon as possible
var resolvedPromisesArray = [Promise.resolve(33), Promise.resolve(44)];

var p = Promise.all(resolvedPromisesArray);
// immediately logging the value of p
console.log(p);

// using setTimeout we can execute code after the stack is empty
setTimeout(function() {
    console.log('the stack is now empty');
    console.log(p);
});

// logs, in order:
// Promise { <state>: "pending" }
// the stack is now empty
// Promise { <state>: "fulfilled", <value>: Array[2] }

The same thing happens if Promise.all rejects:

var mixedPromisesArray = [Promise.resolve(33), Promise.reject(44)];
var p = Promise.all(mixedPromisesArray);
console.log(p);
setTimeout(function() {
    console.log('the stack is now empty');
    console.log(p);
});

// logs
// Promise { <state>: "pending" }
// the stack is now empty
// Promise { <state>: "rejected", <reason>: 44 }

But, Promise.all resolves synchronously if and only if the iterable passed is empty:

var p = Promise.all([]); // will be immediately resolved
var p2 = Promise.all([1337, "hi"]); // non-promise values will be ignored, but the evaluation will be done asynchronously
console.log(p);
console.log(p2)
setTimeout(function() {
    console.log('the stack is now empty');
    console.log(p2);
});

// logs
// Promise { <state>: "fulfilled", <value>: Array[0] }
// Promise { <state>: "pending" }
// the stack is now empty
// Promise { <state>: "fulfilled", <value>: Array[2] }

Promise.all fail-fast behavior

Promise.all is rejected if any of the elements are rejected. For example, if you pass in four promises that resolve after a timeout and one promise that rejects immediately, then Promise.all will reject immediately.

var p1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('one'), 1000);
});
var p2 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('two'), 2000);
});
var p3 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('three'), 3000);
});
var p4 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('four'), 4000);
});
var p5 = new Promise((resolve, reject) => {
  reject(new Error('reject'));
});

// Using .catch:
Promise.all([p1, p2, p3, p4, p5])
.then(values => {
  console.log(values);
})
.catch(error => {
  console.error(error.message)
});

//From console:
//"reject"

It is possible to change this behavior by handling possible rejections:

var p1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('p1_delayed_resolution'), 1000);
});

var p2 = new Promise((resolve, reject) => {
  reject(new Error('p2_immediate_rejection'));
});

Promise.all([
  p1.catch(error => { return error }),
  p2.catch(error => { return error }),
]).then(values => {
  console.log(values[0]) // "p1_delayed_resolution"
  console.error(values[1]) // "Error: p2_immediate_rejection"
})

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-promise.all

all

32

12

29

No

19

8

4.4.3

32

29

19

8

2.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/Global_Objects/Promise/all

Promise.allSettled()

The Promise.allSettled() method returns a promise that resolves after all of the given promises have either fulfilled or rejected, with an array of objects that each describes the outcome of each promise.

It is typically used when you have multiple asynchronous tasks that are not dependent on one another to complete successfully, or you'd always like to know the result of each promise.

In comparison, the Promise returned by Promise.all() may be more appropriate if the tasks are dependent on each other / if you'd like to immediately reject upon any of them rejecting.

Syntax

Promise.allSettled(iterable);

Parameters

iterable
An iterable object, such as an Array, in which each member is a Promise.

Return value

A pending Promise that will be asynchronously fulfilled once every promise in the specified collection of promises has completed, either by successfully being fulfilled or by being rejected. At that time, the returned promise's handler is passed as input an array containing the outcome of each promise in the original set of promises.

However, if and only if an empty iterable is passed as an argument, Promise.allSettled() returns a Promise object that has already been resolved as an empty array.

For each outcome object, a status string is present. If the status is fulfilled, then a value is present. If the status is rejected, then a reason is present. The value (or reason) reflects what value each promise was fulfilled (or rejected) with.

Examples

Using Promise.allSettled

Promise.allSettled([
  Promise.resolve(33),
  new Promise(resolve => setTimeout(() => resolve(66), 0)),
  99,
  Promise.reject(new Error('an error'))
])
.then(values => console.log(values));

// [
//   {status: "fulfilled", value: 33},
//   {status: "fulfilled", value: 66},
//   {status: "fulfilled", value: 99},
//   {status: "rejected",  reason: Error: an error}
// ]

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-promise.allsettled

allSettled

76

79

71

No

63

13

76

76

79

54

13

12.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/Global_Objects/Promise/allSettled

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

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

String.prototype.anchor()

Deprecated

This feature is no longer recommended. Though some browsers might still support it, it may have already been removed from the relevant web standards, may be in the process of being dropped, or may only be kept for compatibility purposes. Avoid using it, and update existing code if possible; see the compatibility table at the bottom of this page to guide your decision. Be aware that this feature may cease to work at any time.

The anchor() method creates a string beginning with an <a name="..."> start tag, then some text, and then an </a> end tag.

Warning: Don't use this method. Use DOM APIs instead. Also, the HTML specification no longer allows the <a> element to have a name attribute, so this method doesn't even create valid markup.

Syntax

anchor(name)

Parameters

name
A string representing a name value to put into the generated <a name="..."> start tag.

Return value

A string beginning with an <a name="name"> start tag, then the text str, and then an </a> end tag.

Description

Don't use this method. Use DOM APIs instead. Also, the HTML specification no longer allows the <a> element to have a name attribute, so this method doesn't even create valid markup.

Examples

Using anchor()

var myString = 'Table of Contents';

document.body.innerHTML = myString.anchor('contents_anchor');

will output the following HTML:

<a name="contents_anchor">Table of Contents</a>

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-string.prototype.anchor

anchor

1

12

1

Starting with version 17, the quotation mark (") is replaced by its HTML reference character (") in strings supplied for the name parameter.

No

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/Global_Objects/String/anchor

Atomics.and()

The static Atomics``.and() method computes a bitwise AND 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.and(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 AND.

value
The number to compute the bitwise AND 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 AND operation only yields 1, if both a and b are 1. The truth table for the AND operation is:

a b a & b
0 0 0
0 1 0
1 0 0
1 1 1

For example, a bitwise AND of 5 & 1 results in 0001 which is 1 in decimal.

5  0101
1  0001
   ----
1  0001

Examples

Using and()

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

Atomics.and(ta, 0, 1); // returns 0, the old value
Atomics.load(ta, 0);  // 1

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-atomics.and

and

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/and

Promise.any()

Promise.any() takes an iterable of Promise objects and, as soon as one of the promises in the iterable fulfills, returns a single promise that resolves with the value from that promise. If no promises in the iterable fulfill (if all of the given promises are rejected), then the returned promise is rejected with an AggregateError, a new subclass of Error that groups together individual errors. Essentially, this method is the opposite of Promise.all().

Syntax

Promise.any(iterable);

Parameters

iterable
An iterable object, such as an Array.

Return value

  • An already rejected Promise if the iterable passed is empty.
  • An asynchronously resolved Promise if the iterable passed contains no promises.
  • A pending Promise in all other cases. This returned promise is then resolved/rejected asynchronously (as soon as the stack is empty) when any of the promises in the given iterable resolve, or if all the promises have rejected.

Description

This method is useful for returning the first promise that fulfills. It short-circuits after a promise fulfills, so it does not wait for the other promises to complete once it finds one. Unlike Promise.all(), which returns an array of fulfillment values, we only get one fulfillment value (assuming at least one promise fulfills). This can be beneficial if we need only one promise to fulfill but we do not care which one does. Note another difference: This method rejects upon receiving an empty iterable, since, truthfully, the iterable contains no items that fulfill.

Also, unlike Promise.race(), which returns the first settled value (either fulfillment or rejection), this method returns the first fulfilled value. This method will ignore all rejected promises up until the first promise that fulfils.

Fulfillment

The returned promise is fulfilled with the first resolved value (or non-promise value) in the iterable passed as the argument, whether or not the other promises have rejected.

  • If a nonempty iterable is passed, and any of the promises fulfill, or are not promises, then the promise returned by this method is fulfilled asynchronously.

Rejection

If all of the passed-in promises reject, Promise.any asynchronously rejects with an AggregateError object, which extends Error, and contains an errors property with an array of rejection values.

  • If an empty iterable is passed, then the promise returned by this method is rejected synchronously. The rejected reason is an AggregateError object whose errors property is an empty array.

Examples

First to fulfil

Promise.any() resolves with the first promise to fulfil, even if a promise rejects first. This is in contrast to Promise.race(), which resolves or rejects with the first promise to settle.

const pErr = new Promise((resolve, reject) => {
  reject("Always fails");
});

const pSlow = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, "Done eventually");
});

const pFast = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, "Done quick");
});

Promise.any([pErr, pSlow, pFast]).then((value) => {
  console.log(value);
  // pFast fulfils first
})
// expected output: "Done quick"

Rejections with AggregateError

Promise.any() rejects with an AggregateError if no promise fulfils.

const pErr = new Promise((resolve, reject) => {
  reject('Always fails');
});

Promise.any([pErr]).catch((err) => {
  console.log(err);
})
// expected output: "AggregateError: No Promise in Promise.any was resolved"

Displaying the first image loaded

In this example, we have a function that fetches an image and returns a blob. We use Promise.any() to fetch a couple of images and display the first one available (i.e. whose promise has resolved).

function fetchAndDecode(url) {
  return fetch(url).then(response => {
    if(!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    } else {
      return response.blob();
    }
  })
}

let coffee = fetchAndDecode('coffee.jpg');
let tea = fetchAndDecode('tea.jpg');

Promise.any([coffee, tea]).then(value => {
  let objectURL = URL.createObjectURL(value);
  let image = document.createElement('img');
  image.src = objectURL;
  document.body.appendChild(image);
})
.catch(e => {
  console.log(e.message);
});

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-promise.any

any

85

85

79

No

No

14

85

85

79

No

14

No

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/Global_Objects/Promise/any

Function.prototype.apply()

The apply() method calls a function with a given this value, and arguments provided as an array (or an array-like object).

Syntax

apply(thisArg)
apply(thisArg, argsArray)

Parameters

thisArg
The value of this provided for the call to func.

Note that this may not be the actual value seen by the method: if the method is a function in non-strict mode code, null and undefined will be replaced with the global object, and primitive values will be boxed. This argument is required.

argsArray Optional
An array-like object, specifying the arguments with which func should be called, or null or undefined if no arguments should be provided to the function.

Starting with ECMAScript 5 these arguments can be a generic array-like object instead of an array. See below for browser compatibility information.

Return value

The result of calling the function with the specified this value and arguments.

Description

Note: While the syntax of this function is almost identical to that of call(), the fundamental difference is that call() accepts an argument list, while apply() accepts a single array of arguments.

Note: When the first argument is undefined or null a similar outcome can be achieved using the array spread syntax.

You can assign a different this object when calling an existing function. this refers to the current object (the calling object). With apply, you can write a method once, and then inherit it in another object, without having to rewrite the method for the new object.

apply is very similar to call(), except for the type of arguments it supports. You use an arguments array instead of a list of arguments (parameters). With apply, you can also use an array literal, for example, func.apply(this, ['eat', 'bananas']), or an Array object, for example, func.apply(this, new Array('eat', 'bananas')).

You can also use arguments for the argsArray parameter. arguments is a local variable of a function. It can be used for all unspecified arguments of the called object. Thus, you do not have to know the arguments of the called object when you use the apply method. You can use arguments to pass all the arguments to the called object. The called object is then responsible for handling the arguments.

Since ECMAScript 5th Edition, you can also use any kind of object which is array-like. In practice, this means it's going to have a length property, and integer ("index") properties in the range (0..length - 1). For example, you could use a NodeList, or a custom object like { 'length': 2, '0': 'eat', '1': 'bananas' }.

Note: Many older browsers—including Chrome <17 and Internet Explorer <9—don't accept array-like objects, and will throw an exception.

Examples

Using apply to append an array to another

You can use push to append an element to an array. And, because push accepts a variable number of arguments, you can also push multiple elements at once.

But, if you pass an array to push, it will actually add that array as a single element, instead of adding the elements individually. So you end up with an array inside an array.

What if that is not what you want? concat does have the desired behavior in this case, but it does not append to the existing array—it instead creates and returns a new array.

But you wanted to append to the existing array... So what now? Write a loop? Surely not?

apply to the rescue!

const array = ['a', 'b'];
const elements = [0, 1, 2];
array.push.apply(array, elements);
console.info(array); // ["a", "b", 0, 1, 2]

Using apply and built-in functions

Clever usage of apply allows you to use built-in functions for some tasks that would probably have otherwise been written by looping over the array values.

As an example, here are Math.max/Math.min, used to find out the maximum/minimum value in an array.

// min/max number in an array
const numbers = [5, 6, 2, 3, 7];

// using Math.min/Math.max apply
let max = Math.max.apply(null, numbers);
// This about equal to Math.max(numbers[0], ...)
// or Math.max(5, 6, ...)

let min = Math.min.apply(null, numbers);

// vs. simple loop based algorithm
max = -Infinity, min = +Infinity;

for (let i = 0; i < numbers.length; i++) {
  if (numbers[i] > max) {
    max = numbers[i];
  }
  if (numbers[i] < min) {
    min = numbers[i];
  }
}

But beware: by using apply this way, you run the risk of exceeding the JavaScript engine's argument length limit. The consequences of applying a function with too many arguments (that is, more than tens of thousands of arguments) varies across engines. (The JavaScriptCore engine has hard-coded argument limit of 65536.

This is because the limit (and indeed, even the nature of any excessively-large-stack behavior) is unspecified. Some engines will throw an exception. More perniciously, others will arbitrarily limit the number of arguments actually passed to the applied function. To illustrate this latter case: if such an engine had a limit of four arguments (actual limits are of course significantly higher), it would be as if the arguments 5, 6, 2, 3 had been passed to apply in the examples above, rather than the full array.

If your value array might grow into the tens of thousands, use a hybrid strategy: apply your function to chunks of the array at a time:

function minOfArray(arr) {
  let min = Infinity;
  let QUANTUM = 32768;

  for (var i = 0, len = arr.length; i < len; i += QUANTUM) {
    var submin = Math.min.apply(null,
                                arr.slice(i, Math.min(i+QUANTUM, len)));
    min = Math.min(submin, min);
  }

  return min;
}

let min = minOfArray([5, 6, 2, 3, 7]);

Using apply to chain constructors

You can use apply to chain constructors for an object (similar to Java).

In the following example we will create a global Function method called construct, which will enable you to use an array-like object with a constructor instead of an arguments list.

Function.prototype.construct = function(aArgs) {
  let oNew = Object.create(this.prototype);
  this.apply(oNew, aArgs);
  return oNew;
};

Example usage:

function MyConstructor() {
  for (let nProp = 0; nProp < arguments.length; nProp++) {
    this['property' + nProp] = arguments[nProp];
  }
}

let myArray = [4, 'Hello world!', false];
let myInstance = MyConstructor.construct(myArray);

console.log(myInstance.property1);                // logs 'Hello world!'
console.log(myInstance instanceof MyConstructor); // logs 'true'
console.log(myInstance.constructor);              // logs 'MyConstructor'

Note: This non-native Function.construct method will not work with some native constructors; like Date, for example. In these cases you have to use the Function.prototype.bind method.

For example, imagine having an array like the following, to be used with Date constructor: [2012, 11, 4]; in this case you have to write something like: new (Function.prototype.bind.apply(Date, [null].concat([2012, 11, 4])))().

This is not the best way to do things, and probably not to be used in any production environment.

The arguments object

arguments is an Array-like object accessible inside functions that contains the values of the arguments passed to that function.

Description

Note: If you're writing ES6 compatible code, then rest parameters should be preferred.

Note: "Array-like” means that arguments has a length property and properties indexed from zero, but it doesn't have Array's built-in methods like forEach() or map(). See §Description for details.

The arguments object is a local variable available within all non-arrow functions. You can refer to a function's arguments inside that function by using its arguments object. It has entries for each argument the function was called with, with the first entry's index at 0.

For example, if a function is passed 3 arguments, you can access them as follows:

arguments[0] // first argument
arguments[1] // second argument
arguments[2] // third argument

Each argument can also be set or reassigned:

arguments[1] = 'new value';

The arguments object is not an Array. It is similar, but lacks all Array properties except length. For example, it does not have the pop() method.

However, it can be converted to a real Array:

var args = Array.prototype.slice.call(arguments);
// Using an array literal is shorter than above but allocates an empty array
var args = [].slice.call(arguments);

As you can do with any Array-like object, you can use ES2015's Array.from() method or spread syntax to convert arguments to a real Array:

let args = Array.from(arguments);
// or
let args = [...arguments];

The arguments object is useful for functions called with more arguments than they are formally declared to accept. This technique is useful for functions that can be passed a variable number of arguments, such as Math.min(). This example function accepts any number of string arguments and returns the longest one:

function longestString() {
  var longest = '';
  for (var i=0; i < arguments.length; i++) {
    if (arguments[i].length > longest.length) {
      longest = arguments[i];
    }
  }
  return longest;
}

You can use arguments.length to count how many arguments the function was called with. If you instead want to count how many parameters a function is declared to accept, inspect that function's length property.

Using typeof with arguments

The typeof operator returns 'object' when used with arguments

console.log(typeof arguments); // 'object'

The type of individual arguments can be determined by indexing arguments:

console.log(typeof arguments[0]); // returns the type of the first argument

Properties

arguments.callee
Reference to the currently executing function that the arguments belong to. Forbidden in strict mode.

arguments.length
The number of arguments that were passed to the function.

arguments[@@iterator]
Returns a new Array iterator object that contains the values for each index in arguments.

Examples

Defining a function that concatenates several strings

This example defines a function that concatenates several strings. The function's only formal argument is a string containing the characters that separate the items to concatenate.

function myConcat(separator) {
  let args = Array.prototype.slice.call(arguments, 1);
  return args.join(separator);
}

You can pass as many arguments as you like to this function. It returns a string list using each argument in the list:

// returns "red, orange, blue"
myConcat(', ', 'red', 'orange', 'blue');

// returns "elephant; giraffe; lion; cheetah"
myConcat('; ', 'elephant', 'giraffe', 'lion', 'cheetah');

// returns "sage. basil. oregano. pepper. parsley"
myConcat('. ', 'sage', 'basil', 'oregano', 'pepper', 'parsley');

Defining a function that creates HTML lists

This example defines a function that creates a string containing HTML for a list. The only formal argument for the function is a string that is "u" if the list is to be unordered (bulleted), or "o" if the list is to be ordered (numbered). The function is defined as follows:

function list(type) {
  var html = '<' + type + 'l><li>';
  var args = Array.prototype.slice.call(arguments, 1);
  html += args.join('</li><li>');
  html += '</li></' + type + 'l>'; // end list
  return html;
}

You can pass any number of arguments to this function, and it adds each argument as a list item to a list of the type indicated. For example:

let listHTML = list('u', 'One', 'Two', 'Three');

/* listHTML is:
"<ul><li>One</li><li>Two</li><li>Three</li></ul>"
*/

Rest, default, and destructured parameters

The arguments object can be used in conjunction with rest, default, and destructured parameters.

function foo(...args) {
  return args;
}
foo(1, 2, 3); // [1, 2, 3]

While the presence of rest, default, or destructured parameters does not alter the behavior of the arguments object in strict mode code, there are subtle differences for non-strict code.

In strict-mode code, the arguments object behaves the same whether or not a function is passed rest, default, or destructured parameters. That is, assigning new values to variables in the body of the function will not affect the arguments object. Nor will assigning new variables to the arguments object affect the value of variables.

Note: You cannot write a "use strict"; directive in the body of a function definition that accepts rest, default, or destructured parameters. Doing so will throw a syntax error.

Non-strict functions that are passed only simple parameters (that is, not rest, default, or restructured parameters) will sync the value of variables new values in the body of the function with the arguments object, and vice versa:

function func(a) {
  arguments[0] = 99; // updating arguments[0] also updates a
  console.log(a);
}
func(10); // 99

And also:

function func(a) {
  a = 99; // updating a also updates arguments[0]
  console.log(arguments[0]);
}
func(10); // 99

Conversely, non-strict functions that are passed rest, default, or destructured parameters will not sync new values assigned to argument variables in the function body with the arguments object. Instead, the arguments object in non-strict functions with complex parameters will always reflect the values passed to the function when the function was called (this is the same behavior as exhibited by all strict-mode functions, regardless of the type of variables they are passed):

function func(a = 55) {
  arguments[0] = 99; // updating arguments[0] does not also update a
  console.log(a);
}
func(10); // 10

And also:

function func(a = 55) {
  a = 99; // updating a does not also update arguments[0]
  console.log(arguments[0]);
}
func(10); // 10

And also:

// An untracked default parameter
function func(a = 55) {
  console.log(arguments[0]);
}
func(); // undefined

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-arguments-exotic-objects

arguments

1

12

1

3

3

1

1

18

4

10.1

1

1.0

callee

1

12

1

6

4

1

1

18

4

10.1

1

1.0

length

1

12

1

4

4

1

1

18

4

10.1

1

1.0

@@iterator

52

12

46

No

39

9

52

52

46

41

9

6.0

See also

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments

Array

The JavaScript Array class is a global object that is used in the construction of arrays; which are high-level, list-like objects.

Description

Arrays are list-like objects whose prototype has methods to perform traversal and mutation operations. Neither the length of a JavaScript array nor the types of its elements are fixed. Since an array's length can change at any time, and data can be stored at non-contiguous locations in the array, JavaScript arrays are not guaranteed to be dense; this depends on how the programmer chooses to use them. In general, these are convenient characteristics; but if these features are not desirable for your particular use, you might consider using typed arrays.

Arrays cannot use strings as element indexes (as in an associative array) but must use integers. Setting or accessing via non-integers using bracket notation (or dot notation) will not set or retrieve an element from the array list itself, but will set or access a variable associated with that array's object property collection. The array's object properties and list of array elements are separate, and the array's traversal and mutation operations cannot be applied to these named properties.

Common operations

Create an Array

let fruits = ['Apple', 'Banana']

console.log(fruits.length)
// 2

Access an Array item using the index position

let first = fruits[0]
// Apple

let last = fruits[fruits.length - 1]
// Banana

Loop over an Array

fruits.forEach(function(item, index, array) {
  console.log(item, index)
})
// Apple 0
// Banana 1

Add an item to the end of an Array

let newLength = fruits.push('Orange')
// ["Apple", "Banana", "Orange"]

Remove an item from the end of an Array

let last = fruits.pop() // remove Orange (from the end)
// ["Apple", "Banana"]

Remove an item from the beginning of an Array

let first = fruits.shift() // remove Apple from the front
// ["Banana"]

Add an item to the beginning of an Array

let newLength = fruits.unshift('Strawberry') // add to the front
// ["Strawberry", "Banana"]

Find the index of an item in the Array

fruits.push('Mango')
// ["Strawberry", "Banana", "Mango"]

let pos = fruits.indexOf('Banana')
// 1

Remove an item by index position

let removedItem = fruits.splice(pos, 1) // this is how to remove an item

// ["Strawberry", "Mango"]

Remove items from an index position

let vegetables = ['Cabbage', 'Turnip', 'Radish', 'Carrot']
console.log(vegetables)
// ["Cabbage", "Turnip", "Radish", "Carrot"]

let pos = 1
let n = 2

let removedItems = vegetables.splice(pos, n)
// this is how to remove items, n defines the number of items to be removed,
// starting at the index position specified by pos and progressing toward the end of array.

console.log(vegetables)
// ["Cabbage", "Carrot"] (the original array is changed)

console.log(removedItems)
// ["Turnip", "Radish"]

Copy an Array

let shallowCopy = fruits.slice() // this is how to make a copy
// ["Strawberry", "Mango"]

Accessing array elements

JavaScript arrays are zero-indexed. The first element of an array is at index 0, and the last element is at the index value equal to the value of the array's length property minus 1.

Using an invalid index number returns undefined.

let arr = ['this is the first element', 'this is the second element', 'this is the last element']
console.log(arr[0])              // logs 'this is the first element'
console.log(arr[1])              // logs 'this is the second element'
console.log(arr[arr.length - 1]) // logs 'this is the last element'

Array elements are object properties in the same way that toString is a property (to be specific, however, toString() is a method). Nevertheless, trying to access an element of an array as follows throws a syntax error because the property name is not valid:

console.log(arr.0) // a syntax error

There is nothing special about JavaScript arrays and the properties that cause this. JavaScript properties that begin with a digit cannot be referenced with dot notation and must be accessed using bracket notation.

For example, if you had an object with a property named 3d, it can only be referenced using bracket notation.

let years = [1950, 1960, 1970, 1980, 1990, 2000, 2010]
console.log(years.0)   // a syntax error
console.log(years[0])  // works properly

renderer.3d.setTexture(model, 'character.png')     // a syntax error
renderer['3d'].setTexture(model, 'character.png')  // works properly

In the 3d example, '3d' had to be quoted (because it begins with a digit). But it's also possible to quote the array indexes as well (e.g., years['2'] instead of years[2]), although it's not necessary.

The 2 in years[2] is coerced into a string by the JavaScript engine through an implicit toString conversion. As a result, '2' and '02' would refer to two different slots on the years object, and the following example could be true:

console.log(years['2'] != years['02'])

Relationship between length and numerical properties

A JavaScript array's length property and numerical properties are connected.

Several of the built-in array methods (e.g., join(), slice(), indexOf(), etc.) take into account the value of an array's length property when they're called.

Other methods (e.g., push(), splice(), etc.) also result in updates to an array's length property.

const fruits = []
fruits.push('banana', 'apple', 'peach')

console.log(fruits.length) // 3

When setting a property on a JavaScript array when the property is a valid array index and that index is outside the current bounds of the array, the engine will update the array's length property accordingly:

fruits[5] = 'mango'
console.log(fruits[5])            // 'mango'
console.log(Object.keys(fruits))  // ['0', '1', '2', '5']
console.log(fruits.length)        // 6

Increasing the length.

fruits.length = 10
console.log(fruits)              // ['banana', 'apple', 'peach', empty x 2, 'mango', empty x 4]
console.log(Object.keys(fruits)) // ['0', '1', '2', '5']
console.log(fruits.length)       // 10
console.log(fruits[8])           // undefined

Decreasing the length property does, however, delete elements.

fruits.length = 2
console.log(Object.keys(fruits)) // ['0', '1']
console.log(fruits.length)       // 2

This is explained further on the Array.length page.

Creating an array using the result of a match

The result of a match between a RegExp and a string can create a JavaScript array. This array has properties and elements which provide information about the match. Such an array is returned by RegExp.exec(), String.match(), and String.replace().

To help explain these properties and elements, see this example and then refer to the table below:

// Match one d followed by one or more b's followed by one d
// Remember matched b's and the following d
// Ignore case

const myRe = /d(b+)(d)/i
const myArray = myRe.exec('cdbBdbsbz')

The properties and elements returned from this match are as follows:

Property/Element Description Example
input

Read only

The original string against which the regular expression was matched. "cdbBdbsbz"
index

Read only

The zero-based index of the match in the string. 1
[0]

Read only

The last matched characters. "dbBd"
[1], ...[n]

Read only

Elements that specify the parenthesized substring matches (if included) in the regular expression. The number of possible parenthesized substrings is unlimited. [1]: "bB" [2]: "d"

Constructor

Array()
Creates a new Array object.

Static properties

get Array[@@species]
The constructor function is used to create derived objects.

Static methods

Array.from()
Creates a new Array instance from an array-like or iterable object.

Array.isArray()
Returns true if the argument is an array, or false otherwise.

Array.of()
Creates a new Array instance with a variable number of arguments, regardless of number or type of the arguments.

Instance properties

Array.prototype.length
Reflects the number of elements in an array.

Array.prototype[@@unscopables]
A symbol containing property names to exclude from a with binding scope.

Instance methods

Array.prototype.at() This is an experimental API that should not be used in production code.
Returns the array item at the given index. Accepts negative integers, which count back from the last item.

Array.prototype.concat()
Returns a new array that is this array joined with other array(s) and/or value(s).

Array.prototype.copyWithin()
Copies a sequence of array elements within the array.

Array.prototype.entries()
Returns a new Array Iterator object that contains the key/value pairs for each index in the array.

Array.prototype.every()
Returns true if every element in this array satisfies the testing function.

Array.prototype.fill()
Fills all the elements of an array from a start index to an end index with a static value.

Array.prototype.filter()
Returns a new array containing all elements of the calling array for which the provided filtering function returns true.

Array.prototype.find()
Returns the found element in the array, if some element in the array satisfies the testing function, or undefined if not found.

Array.prototype.findIndex()
Returns the found index in the array, if an element in the array satisfies the testing function, or -1 if not found.

Array.prototype.forEach()
Calls a function for each element in the array.

Array.prototype.includes()
Determines whether the array contains a value, returning true or false as appropriate.

Array.prototype.indexOf()
Returns the first (least) index of an element within the array equal to an element, or -1 if none is found.

Array.prototype.join()
Joins all elements of an array into a string.

Array.prototype.keys()
Returns a new Array Iterator that contains the keys for each index in the array.

Array.prototype.lastIndexOf()
Returns the last (greatest) index of an element within the array equal to an element, or -1 if none is found.

Array.prototype.map()
Returns a new array containing the results of calling a function on every element in this array.

Array.prototype.pop()
Removes the last element from an array and returns that element.

Array.prototype.push()
Adds one or more elements to the end of an array, and returns the new length of the array.

Array.prototype.reduce()
Apply a function against an accumulator and each value of the array (from left-to-right) as to reduce it to a single value.

Array.prototype.reduceRight()
Apply a function against an accumulator> and each value of the array (from right-to-left) as to reduce it to a single value.

Array.prototype.reverse()
Reverses the order of the elements of an array in place. (First becomes the last, last becomes first.)

Array.prototype.shift()
Removes the first element from an array and returns that element.

Array.prototype.slice()
Extracts a section of the calling array and returns a new array.

Array.prototype.some()
Returns true if at least one element in this array satisfies the provided testing function.

Array.prototype.sort()
Sorts the elements of an array in place and returns the array.

Array.prototype.splice()
Adds and/or removes elements from an array.

Array.prototype.toLocaleString()
Returns a localized string representing the array and its elements. Overrides the Object.prototype.toLocaleString() method.

Array.prototype.toString()
Returns a string representing the array and its elements. Overrides the Object.prototype.toString() method.

Array.prototype.unshift()
Adds one or more elements to the front of an array, and returns the new length of the array.

Array.prototype.values()
Returns a new Array Iterator object that contains the values for each index in the array.

Array.prototype[@@iterator]()
Returns a new Array Iterator object that contains the values for each index in the array.

Examples

Creating an array

The following example creates an array, msgArray, with a length of 0, then assigns values to msgArray[0] and msgArray[99], changing the length of the array to 100.

let msgArray = []
msgArray[0] = 'Hello'
msgArray[99] = 'world'

if (msgArray.length === 100) {
  console.log('The length is 100.')
}

Creating a two-dimensional array

The following creates a chessboard as a two-dimensional array of strings. The first move is made by copying the 'p' in board[6][4] to board[4][4]. The old position at [6][4] is made blank.

let board = [
  ['R','N','B','Q','K','B','N','R'],
  ['P','P','P','P','P','P','P','P'],
  [' ',' ',' ',' ',' ',' ',' ',' '],
  [' ',' ',' ',' ',' ',' ',' ',' '],
  [' ',' ',' ',' ',' ',' ',' ',' '],
  [' ',' ',' ',' ',' ',' ',' ',' '],
  ['p','p','p','p','p','p','p','p'],
  ['r','n','b','q','k','b','n','r'] ]

console.log(board.join('\n') + '\n\n')

// Move King's Pawn forward 2
board[4][4] = board[6][4]
board[6][4] = ' '
console.log(board.join('\n'))

Here is the output:

R,N,B,Q,K,B,N,R
P,P,P,P,P,P,P,P
 , , , , , , ,
 , , , , , , ,
 , , , , , , ,
 , , , , , , ,
p,p,p,p,p,p,p,p
r,n,b,q,k,b,n,r

R,N,B,Q,K,B,N,R
P,P,P,P,P,P,P,P
 , , , , , , ,
 , , , , , , ,
 , , , ,p, , ,
 , , , , , , ,
p,p,p,p, ,p,p,p
r,n,b,q,k,b,n,r

Using an array to tabulate a set of values

values = []
for (let x = 0; x < 10; x++){
 values.push([
  2 ** x,
  2 * x ** 2
 ])
}
console.table(values)

Results in

// The first column is the index
0   1   0
1   2   2
2   4   8
3   8   18
4   16  32
5   32  50
6   64  72
7   128 98
8   256 128
9   512 162

TypeError: invalid Array.prototype.sort argument

The JavaScript exception "invalid Array.prototype.sort argument" occurs when the argument of Array.prototype.sort() isn't either undefined or a function which compares its operands.

Message

TypeError: argument is not a function object (Edge)
TypeError: invalid Array.prototype.sort argument (Firefox)

Error type

TypeError

What went wrong?

The argument of Array.prototype.sort() is expected to be either undefined or a function which compares its operands.

Examples

Invalid cases

[1, 3, 2].sort(5);  // TypeError

var cmp = { asc: (x, y) => x >= y, dsc: (x, y) => x <= y };
[1, 3, 2].sort(cmp[this.key] || 'asc');  // TypeError

Valid cases

[1, 3, 2].sort();   // [1, 2, 3]

var cmp = { asc: (x, y) => x >= y, dsc: (x, y) => x <= y };
[1, 3, 2].sort(cmp[this.key || 'asc']); // [1, 2, 3]

See also

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

ArrayBuffer

The ArrayBuffer object is used to represent a generic, fixed-length raw binary data buffer.

It is an array of bytes, often referred to in other languages as a "byte array".You cannot directly manipulate the contents of an ArrayBuffer; instead, you create one of the typed array objects or a DataView object which represents the buffer in a specific format, and use that to read and write the contents of the buffer.

The ArrayBuffer() constructor creates a new ArrayBuffer of the given length in bytes. You can also get an array buffer from existing data, for example from a Base64 string or from a local file.

Constructor

ArrayBuffer()
Creates a new ArrayBuffer object.

Static properties

get ArrayBuffer[@@species]
The constructor function that is used to create derived objects.

Static methods

ArrayBuffer.isView(arg)
Returns true if arg is one of the ArrayBuffer views, such as typed array objects or a DataView. Returns false otherwise.

Instance properties

ArrayBuffer.prototype.byteLength
The read-only size, in bytes, of the ArrayBuffer. This is established when the array is constructed and cannot be changed.

Instance methods

ArrayBuffer.prototype.slice()
Returns a new ArrayBuffer whose contents are a copy of this ArrayBuffer's bytes from begin (inclusive) up to end (exclusive). If either begin or end is negative, it refers to an index from the end of the array, as opposed to from the beginning.

Examples

Creating an ArrayBuffer

In this example, we create a 8-byte buffer with a Int32Array view referring to the buffer:

const buffer = new ArrayBuffer(8);
const view = new Int32Array(buffer);

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-arraybuffer-objects

ArrayBuffer

7

12

4

10

11.6

5.1

4

18

4

12

4.2

1.0

ArrayBuffer

7

12

4

10

11.6

5.1

4

18

4

12

4.2

1.0

byteLength

7

12

4

10

11.6

5.1

4

18

4

12

4.2

1.0

isView

32

12

29

11

19

7

≤37

32

29

19

7

2.0

slice

17

12

12

The non-standard ArrayBuffer.slice() method has been removed in Firefox 53 (but the standardized version ArrayBuffer.prototype.slice() is kept.

11

12.1

6

≤37

18

14

The non-standard ArrayBuffer.slice() method has been removed in Firefox 53 (but the standardized version ArrayBuffer.prototype.slice() is kept.

12.1

6

1.0

@@species

51

13

48

No

38

10

51

51

48

41

10

5.0

See also

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

Arrow function expressions

An arrow function expression is a compact alternative to a traditional function expression, but is limited and can't be used in all situations.

Differences & Limitations:

  • Does not have its own bindings to this or super, and should not be used as methods.
  • Does not have arguments, or new.target keywords.
  • Not suitable for call, apply and bind methods, which generally rely on establishing a scope.
  • Can not be used as constructors.
  • Can not use yield, within its body.

Comparing traditional functions to arrow functions

Let's decompose a "traditional function" down to the simplest "arrow function" step-by-step:
NOTE: Each step along the way is a valid "arrow function"

// Traditional Function
function (a){
  return a + 100;
}

// Arrow Function Break Down

// 1. Remove the word "function" and place arrow between the argument and opening body bracket
(a) => {
  return a + 100;
}

// 2. Remove the body brackets and word "return" -- the return is implied.
(a) => a + 100;

// 3. Remove the argument parentheses
a => a + 100;

Note: As shown above, the { brackets } and ( parentheses ) and "return" are optional, but may be required.

For example, if you have multiple arguments or no arguments, you'll need to re-introduce parentheses around the arguments:

// Traditional Function
function (a, b){
  return a + b + 100;
}

// Arrow Function
(a, b) => a + b + 100;

// Traditional Function (no arguments)
let a = 4;
let b = 2;
function (){
  return a + b + 100;
}

// Arrow Function (no arguments)
let a = 4;
let b = 2;
() => a + b + 100;

Likewise, if the body requires additional lines of processing, you'll need to re-introduce brackets PLUS the "return" (arrow functions do not magically guess what or when you want to "return"):

// Traditional Function
function (a, b){
  let chuck = 42;
  return a + b + chuck;
}

// Arrow Function
(a, b) => {
  let chuck = 42;
  return a + b + chuck;
}

And finally, for named functions we treat arrow expressions like variables

// Traditional Function
function bob (a){
  return a + 100;
}

// Arrow Function
let bob = a => a + 100;

Syntax

Basic syntax

One param. With simple expression return is not needed:

param => expression

Multiple params require parentheses. With simple expression return is not needed:

(param1, paramN) => expression

Multiline statements require body brackets and return:

param => {
  let a = 1;
  return a + param;
}

Multiple params require parentheses. Multiline statements require body brackets and return:

(param1, paramN) => {
   let a = 1;
   return a + param1 + paramN;
}

Advanced syntax

To return an object literal expression requires parentheses around expression:

params => ({foo: "a"}) // returning the object {foo: "a"}

Rest parameters are supported:

(a, b, ...r) => expression

Default parameters are supported:

(a=400, b=20, c) => expression

Destructuring within params supported:

([a, b] = [10, 20]) => a + b;  // result is 30
({ a, b } = { a: 10, b: 20 }) => a + b; // result is 30

Description

Arrow functions used as methods

As stated previously, arrow function expressions are best suited for non-method functions. Let's see what happens when we try to use them as methods:

'use strict';

var obj = { // does not create a new scope
  i: 10,
  b: () => console.log(this.i, this),
  c: function() {
    console.log(this.i, this);
  }
}

obj.b(); // prints undefined, Window {...} (or the global object)
obj.c(); // prints 10, Object {...}

Arrow functions do not have their own this. Another example involving Object.defineProperty():

'use strict';

var obj = {
  a: 10
};

Object.defineProperty(obj, 'b', {
  get: () => {
    console.log(this.a, typeof this.a, this); // undefined 'undefined' Window {...} (or the global object)
    return this.a + 10; // represents global object 'Window', therefore 'this.a' returns 'undefined'
  }
});

call, apply and bind

The call, apply and bind methods are NOT suitable for Arrow functions -- as they were designed to allow methods to execute within different scopes -- because Arrow functions establish "this" based on the scope the Arrow function is defined within.

For example call, apply and bind work as expected with Traditional functions, because we establish the scope for each of the methods:

// ----------------------
// Traditional Example
// ----------------------
// A simplistic object with its very own "this".
var obj = {
    num: 100
}

// Setting "num" on window to show how it is NOT used.
window.num = 2020; // yikes!

// A simple traditional function to operate on "this"
var add = function (a, b, c) {
  return this.num + a + b + c;
}

// call
var result = add.call(obj, 1, 2, 3) // establishing the scope as "obj"
console.log(result) // result 106

// apply
const arr = [1, 2, 3]
var result = add.apply(obj, arr) // establishing the scope as "obj"
console.log(result) // result 106

// bind
var result = add.bind(obj) // establishing the scope as "obj"
console.log(result(1, 2, 3)) // result 106

With Arrow functions, since our add function is essentially created on the window (global) scope, it will assume this is the window.

// ----------------------
// Arrow Example
// ----------------------

// A simplistic object with its very own "this".
var obj = {
    num: 100
}

// Setting "num" on window to show how it gets picked up.
window.num = 2020; // yikes!

// Arrow Function
var add = (a, b, c) => this.num + a + b + c;

// call
console.log(add.call(obj, 1, 2, 3)) // result 2026

// apply
const arr = [1, 2, 3]
console.log(add.apply(obj, arr)) // result 2026

// bind
const bound = add.bind(obj)
console.log(bound(1, 2, 3)) // result 2026

Perhaps the greatest benefit of using Arrow functions is with DOM-level methods (setTimeout, setInterval, addEventListener) that usually required some kind of closure, call, apply or bind to ensure the function executed in the proper scope.

Traditional Example:

var obj = {
    count : 10,
    doSomethingLater : function (){
        setTimeout(function(){ // the function executes on the window scope
            this.count++;
            console.log(this.count);
        }, 300);
    }
}

obj.doSomethingLater(); // console prints "NaN", because the property "count" is not in the window scope.

Arrow Example:

var obj = {
    count : 10,
    doSomethingLater : function(){ // of course, arrow functions are not suited for methods
        setTimeout( () => { // since the arrow function was created within the "obj", it assumes the object's "this"
            this.count++;
            console.log(this.count);
        }, 300);
    }
}

obj.doSomethingLater();

No binding of arguments

Arrow functions do not have their own arguments object. Thus, in this example, arguments is a reference to the arguments of the enclosing scope:

var arguments = [1, 2, 3];
var arr = () => arguments[0];

arr(); // 1

function foo(n) {
  var f = () => arguments[0] + n; // foo's implicit arguments binding. arguments[0] is n
  return f();
}

foo(3); // 3 + 3 = 6

In most cases, using rest parameters is a good alternative to using an arguments object.

function foo(n) {
  var f = (...args) => args[0] + n;
  return f(10);
}

foo(1); // 11

Use of the new operator

Arrow functions cannot be used as constructors and will throw an error when used with new.

var Foo = () => {};
var foo = new Foo(); // TypeError: Foo is not a constructor

Use of prototype property

Arrow functions do not have a prototype property.

var Foo = () => {};
console.log(Foo.prototype); // undefined

Use of the yield keyword

The yield keyword may not be used in an arrow function's body (except when permitted within functions further nested within it). As a consequence, arrow functions cannot be used as generators.

Function body

Arrow functions can have either a "concise body" or the usual "block body".

In a concise body, only an expression is specified, which becomes the implicit return value. In a block body, you must use an explicit return statement.

var func = x => x * x;
// concise body syntax, implied "return"

var func = (x, y) => { return x + y; };
// with block body, explicit "return" needed

Returning object literals

Keep in mind that returning object literals using the concise body syntax params => {object:literal} will not work as expected.

var func = () => { foo: 1 };
// Calling func() returns undefined!

var func = () => { foo: function() {} };
// SyntaxError: function statement requires a name

This is because the code inside braces ({}) is parsed as a sequence of statements (i.e. foo is treated like a label, not a key in an object literal).

You must wrap the object literal in parentheses:

var func = () => ({ foo: 1 });

Line breaks

An arrow function cannot contain a line break between its parameters and its arrow.

var func = (a, b, c)
  => 1;
// SyntaxError: expected expression, got '=>'

However, this can be amended by putting the line break after the arrow or using parentheses/braces as seen below to ensure that the code stays pretty and fluffy. You can also put line breaks between arguments.

var func = (a, b, c) =>
  1;

var func = (a, b, c) => (
  1
);

var func = (a, b, c) => {
  return 1
};

var func = (
  a,
  b,
  c
) => 1;

// no SyntaxError thrown

Parsing order

Although the arrow in an arrow function is not an operator, arrow functions have special parsing rules that interact differently with operator precedence compared to regular functions.

let callback;

callback = callback || function() {}; // ok

callback = callback || () => {};
// SyntaxError: invalid arrow-function arguments

callback = callback || (() => {});    // ok

Examples

Basic usage

// An empty arrow function returns undefined
let empty = () => {};

(() => 'foobar')();
// Returns "foobar"
// (this is an Immediately Invoked Function Expression)

var simple = a => a > 15 ? 15 : a;
simple(16); // 15
simple(10); // 10

let max = (a, b) => a > b ? a : b;

// Easy array filtering, mapping, ...

var arr = [5, 6, 13, 0, 1, 18, 23];

var sum = arr.reduce((a, b) => a + b);
// 66

var even = arr.filter(v => v % 2 == 0);
// [6, 0, 18]

var double = arr.map(v => v * 2);
// [10, 12, 26, 0, 2, 36, 46]

// More concise promise chains
promise.then(a => {
  // ...
}).then(b => {
  // ...
});

// Parameterless arrow functions that are visually easier to parse
setTimeout( () => {
  console.log('I happen sooner');
  setTimeout( () => {
    // deeper code
    console.log('I happen later');
  }, 1);
}, 1);

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-arrow-function-definitions

Arrow_functions

45

12

22

["The initial implementation of arrow functions in Firefox made them automatically strict. This has been changed as of Firefox 24. The use of 'use strict'; is now required.", "Prior to Firefox 39, a line terminator (\\n) was incorrectly allowed after arrow function arguments. This has been fixed to conform to the ES2015 specification and code like () \\n => {} will now throw a SyntaxError in this and later versions."]

No

32

10

45

45

22

["The initial implementation of arrow functions in Firefox made them automatically strict. This has been changed as of Firefox 24. The use of 'use strict'; is now required.", "Prior to Firefox 39, a line terminator (\\n) was incorrectly allowed after arrow function arguments. This has been fixed to conform to the ES2015 specification and code like () \\n => {} will now throw a SyntaxError in this and later versions."]

32

10

5.0

trailing_comma

58

12

52

No

45

10

58

58

52

43

10

7.0

See also

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Math.asin()

The Math.asin() function returns the arcsine (in radians) of a number, that is

$$\forall x \in \lbrack{- 1};1\rbrack,\;\mathtt{\operatorname{Math.asin}(x)} = \arcsin(x) = \text{the\ unique}\; y \in \left\lbrack {- \frac{\pi}{2};\frac{\pi}{2}} \right\rbrack\,\text{such\ that}\;\sin(y) = x$$

Syntax

Math.asin(x)

Parameters

x
A number.

Return value

The arcsine (in radians) of the given number if it's between -1 and 1; otherwise, NaN.

Description

The Math.asin() method returns a numeric value between $- \frac{\pi}{2}$ and $\frac{\pi}{2}$ radians for x between -1 and 1. If the value of x is outside this range, it returns NaN.

Because asin() is a static method of Math, you always use it as Math.asin(), rather than as a method of a Math object you created (Math is not a constructor).

Examples

Using Math.asin()

Math.asin(-2);  // NaN
Math.asin(-1);  // -1.5707963267948966 (-pi/2)
Math.asin(0);   // 0
Math.asin(0.5); // 0.5235987755982989
Math.asin(1);   // 1.5707963267948966 (pi/2)
Math.asin(2);   // NaN

For values less than -1 or greater than 1, Math.asin() returns NaN.

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-math.asin

asin

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/Global_Objects/Math/asin

Math.asinh()

The Math.asinh() function returns the hyperbolic arcsine of a number, that is

Math.asinh(``x``) = arsinh (x) = the unique y such that sinh (y) = x

Syntax

Math.asinh(x)

Parameters

x
A number.

Return value

The hyperbolic arcsine of the given number.

Description

Because asinh() is a static method of Math, you always use it as Math.asinh(), rather than as a method of a Math object you created (Math is not a constructor).

Examples

Using Math.asinh()

Math.asinh(1);  // 0.881373587019543
Math.asinh(0);  // 0

Polyfill

Math.asinh can be emulated with the following function:

if (!Math.asinh) Math.asinh = function(x) {
    var absX = Math.abs(x), w
    if (absX < 3.725290298461914e-9) // |x| < 2^-28
        return x
    if (absX > 268435456) // |x| > 2^28
        w = Math.log(absX) + Math.LN2
    else if (absX > 2) // 2^28 >= |x| > 2
        w = Math.log(2 * absX + 1 / (Math.sqrt(x * x + 1) + absX))
    else
        var t = x * x, w = Math.log1p(absX + t / (1 + Math.sqrt(1 + t)))

    return x > 0 ? w : -w
}

Math.log1p may also have to be polyfilled; see Math.log1p for details.

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-math.asinh

asinh

38

12

25

No

25

8

38

38

25

25

8

3.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/Global_Objects/Math/asinh

BigInt.asIntN()

The BigInt.asIntN static method clamps a BigInt value to a signed integer value, and returns that value.

Syntax

BigInt.asIntN(bits, bigint);

Parameters

bits
The amount of bits available for the integer size.

bigint
The BigInt value to clamp to fit into the supplied bits.

Returns

The value of bigint modulo 2bits, as a signed integer.

Examples

Staying in 64-bit ranges

The BigInt.asIntN() method can be useful to stay in the range of 64-bit arithmetic.

const max = 2n ** (64n - 1n) - 1n;

BigInt.asIntN(64, max);
// ↪ 9223372036854775807n

BigInt.asIntN(64, max + 1n);
// ↪ -9223372036854775808n
// negative because of overflow

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-bigint.asintn

asIntN

67

79

68

No

54

14

67

67

68

48

14

9.0

See also

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

Object.assign()

The Object.assign() method copies all enumerable own properties from one or more source objects to a target object. It returns the target object.

Syntax

Object.assign(target, ...sources)

Parameters

target
The target object — what to apply the sources' properties to, which is returned after it is modified.

sources
The source object(s) — objects containing the properties you want to apply.

Return value

The target object.

Description

Properties in the target object are overwritten by properties in the sources if they have the same key. Later sources' properties overwrite earlier ones.

The Object.assign() method only copies enumerable and own properties from a source object to a target object. It uses [[Get]] on the source and [[Set]] on the target, so it will invoke getters and setters. Therefore it assigns properties, versus copying or defining new properties. This may make it unsuitable for merging new properties into a prototype if the merge sources contain getters.

For copying property definitions (including their enumerability) into prototypes, use Object.getOwnPropertyDescriptor() and Object.defineProperty() instead.

Both String and Symbol properties are copied.

In case of an error, for example if a property is non-writable, a TypeError is raised, and the target object is changed if any properties are added before the error is raised.

Note: Object.assign() does not throw on null or undefined sources.

Polyfill

This polyfill doesn't support symbol properties, since ES5 doesn't have symbols anyway:

if (typeof Object.assign !== 'function') {
  // Must be writable: true, enumerable: false, configurable: true
  Object.defineProperty(Object, "assign", {
    value: function assign(target, varArgs) { // .length of function is 2
      'use strict';
      if (target === null || target === undefined) {
        throw new TypeError('Cannot convert undefined or null to object');
      }

      var to = Object(target);

      for (var index = 1; index < arguments.length; index++) {
        var nextSource = arguments[index];

        if (nextSource !== null && nextSource !== undefined) {
          for (var nextKey in nextSource) {
            // Avoid bugs when hasOwnProperty is shadowed
            if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
              to[nextKey] = nextSource[nextKey];
            }
          }
        }
      }
      return to;
    },
    writable: true,
    configurable: true
  });
}

Examples

Cloning an object

const obj = { a: 1 };
const copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }

Warning for Deep Clone

For deep cloning, we need to use alternatives, because Object.assign() copies property values.

If the source value is a reference to an object, it only copies the reference value.

function test() {
  'use strict';

  let obj1 = { a: 0 , b: { c: 0}};
  let obj2 = Object.assign({}, obj1);
  console.log(JSON.stringify(obj2)); // { "a": 0, "b": { "c": 0}}

  obj1.a = 1;
  console.log(JSON.stringify(obj1)); // { "a": 1, "b": { "c": 0}}
  console.log(JSON.stringify(obj2)); // { "a": 0, "b": { "c": 0}}

  obj2.a = 2;
  console.log(JSON.stringify(obj1)); // { "a": 1, "b": { "c": 0}}
  console.log(JSON.stringify(obj2)); // { "a": 2, "b": { "c": 0}}

  obj2.b.c = 3;
  console.log(JSON.stringify(obj1)); // { "a": 1, "b": { "c": 3}}
  console.log(JSON.stringify(obj2)); // { "a": 2, "b": { "c": 3}}

  // Deep Clone
  obj1 = { a: 0 , b: { c: 0}};
  let obj3 = JSON.parse(JSON.stringify(obj1));
  obj1.a = 4;
  obj1.b.c = 4;
  console.log(JSON.stringify(obj3)); // { "a": 0, "b": { "c": 0}}
}

test();

Merging objects

const o1 = { a: 1 };
const o2 = { b: 2 };
const o3 = { c: 3 };

const obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1);  // { a: 1, b: 2, c: 3 }, target object itself is changed.

Merging objects with same properties

const o1 = { a: 1, b: 1, c: 1 };
const o2 = { b: 2, c: 2 };
const o3 = { c: 3 };

const obj = Object.assign({}, o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }

The properties are overwritten by other objects that have the same properties later in the parameters order.

Copying symbol-typed properties

const o1 = { a: 1 };
const o2 = { [Symbol('foo')]: 2 };

const obj = Object.assign({}, o1, o2);
console.log(obj); // { a : 1, [Symbol("foo")]: 2 } (cf. bug 1207182 on Firefox)
Object.getOwnPropertySymbols(obj); // [Symbol(foo)]

Properties on the prototype chain and non-enumerable properties cannot be copied

const obj = Object.create({ foo: 1 }, { // foo is on obj's prototype chain.
  bar: {
    value: 2  // bar is a non-enumerable property.
  },
  baz: {
    value: 3,
    enumerable: true  // baz is an own enumerable property.
  }
});

const copy = Object.assign({}, obj);
console.log(copy); // { baz: 3 }

Primitives will be wrapped to objects

const v1 = 'abc';
const v2 = true;
const v3 = 10;
const v4 = Symbol('foo');

const obj = Object.assign({}, v1, null, v2, undefined, v3, v4);
// Primitives will be wrapped, null and undefined will be ignored.
// Note, only string wrappers can have own enumerable properties.
console.log(obj); // { "0": "a", "1": "b", "2": "c" }

Exceptions will interrupt the ongoing copying task

const target = Object.defineProperty({}, 'foo', {
  value: 1,
  writable: false
}); // target.foo is a read-only property

Object.assign(target, { bar: 2 }, { foo2: 3, foo: 3, foo3: 3 }, { baz: 4 });
// TypeError: "foo" is read-only
// The Exception is thrown when assigning target.foo

console.log(target.bar);  // 2, the first source was copied successfully.
console.log(target.foo2); // 3, the first property of the second source was copied successfully.
console.log(target.foo);  // 1, exception is thrown here.
console.log(target.foo3); // undefined, assign method has finished, foo3 will not be copied.
console.log(target.baz);  // undefined, the third source will not be copied either.

Copying accessors

const obj = {
  foo: 1,
  get bar() {
    return 2;
  }
};

let copy = Object.assign({}, obj);
console.log(copy);
// { foo: 1, bar: 2 }
// The value of copy.bar is obj.bar's getter's return value.

// This is an assign function that copies full descriptors
function completeAssign(target, ...sources) {
  sources.forEach(source => {
    let descriptors = Object.keys(source).reduce((descriptors, key) => {
      descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
      return descriptors;
    }, {});

    // By default, Object.assign copies enumerable Symbols, too
    Object.getOwnPropertySymbols(source).forEach(sym => {
      let descriptor = Object.getOwnPropertyDescriptor(source, sym);
      if (descriptor.enumerable) {
        descriptors[sym] = descriptor;
      }
    });
    Object.defineProperties(target, descriptors);
  });
  return target;
}

copy = completeAssign({}, obj);
console.log(copy);
// { foo:1, get bar() { return 2 } }

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-object.assign

assign

45

12

34

No

32

9

45

45

34

32

9

5.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/Global_Objects/Object/assign

BigInt.asUintN()

The BigInt.asUintN static method clamps a BigInt value to an unsigned integer value, and returns that value.

Syntax

BigInt.asUintN(bits, bigint);

Parameters

bits
The amount of bits available for the integer size.

bigint
The BigInt value to clamp to fit into the supplied bits.

Returns

The value of bigint modulo 2bits, as an unsigned integer.

Examples

Staying in 64-bit ranges

The BigInt.asUintN() method can be useful to stay in the range of 64-bit arithmetic.

const max = 2n ** 64n - 1n;

BigInt.asUintN(64, max);
// ↪ 18446744073709551615n

BigInt.asUintN(64, max + 1n);
// ↪ 0n
// zero because of overflow

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-bigint.asuintn

asUintN

67

79

68

No

54

14

67

67

68

48

14

9.0

See also

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

async function

An async function is a function declared with the async keyword, and the await keyword is permitted within them. The async and await keywords enable asynchronous, promise-based behavior to be written in a cleaner style, avoiding the need to explicitly configure promise chains.

Async functions may also be defined as expressions.

Syntax

async function name([param[, param[, ...param]]]) {
   statements
}

Parameters

name
The function's name.

param
The name of an argument to be passed to the function.

statements
The statements comprising the body of the function. The await mechanism may be used.

Return value

A Promise which will be resolved with the value returned by the async function, or rejected with an exception thrown from, or uncaught within, the async function.

Description

Async functions can contain zero or more await expressions. Await expressions make promise-returning functions behave as though they're synchronous by suspending execution until the returned promise is fulfilled or rejected. The resolved value of the promise is treated as the return value of the await expression. Use of async and await enables the use of ordinary try / catch blocks around asynchronous code.

Note: The await keyword is only valid inside async functions within regular JavaScript code. If you use it outside of an async function's body, you will get a SyntaxError.

await can be used on its own with JavaScript modules.

Note: The purpose of async/await is to simplify the syntax necessary to consume promise-based APIs. The behavior of async/await is similar to combining generators and promises.

Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.

For example, the following:

async function foo() {
   return 1
}

...is similar to:

function foo() {
   return Promise.resolve(1)
}

Checking equality with Promise.resolve vs async return

Even though the return value of an async function behaves as if it's wrapped in a Promise.resolve, they are not equivalent.

An async function will return a different reference, whereas Promise.resolve returns the same reference if the given value is a promise.

It can be a problem when you want to check the equality of a promise and a return value of an async function.

const p = new Promise((res, rej) => {
  res(1);
})

async function asyncReturn() {
  return p;
}

function basicReturn() {
  return Promise.resolve(p);
}

console.log(p === basicReturn()); // true
console.log(p === asyncReturn()); // false

The body of an async function can be thought of as being split by zero or more await expressions. Top-level code, up to and including the first await expression (if there is one), is run synchronously. In this way, an async function without an await expression will run synchronously. If there is an await expression inside the function body, however, the async function will always complete asynchronously.

For example:

async function foo() {
   await 1
}

...is equivalent to:

function foo() {
   return Promise.resolve(1).then(() => undefined)
}

Code after each await expression can be thought of as existing in a .then callback. In this way a promise chain is progressively constructed with each reentrant step through the function. The return value forms the final link in the chain.

In the following example, we successively await two promises. Progress moves through function foo in three stages.

  1. The first line of the body of function foo is executed synchronously, with the await expression configured with the pending promise. Progress through foo is then suspended and control is yielded back to the function that called foo.
  2. Some time later, when the first promise has either been fulfilled or rejected, control moves back into foo. The result of the first promise fulfillment (if it was not rejected) is returned from the await expression. Here 1 is assigned to result1. Progress continues, and the second await expression is evaluated. Again, progress through foo is suspended and control is yielded.
  3. Some time later, when the second promise has either been fulfilled or rejected, control re-enters foo. The result of the second promise resolution is returned from the second await expression. Here 2 is assigned to result2. Control moves to the return expression (if any). The default return value of undefined is returned as the resolution value of the current promise.
async function foo() {
   const result1 = await new Promise((resolve) => setTimeout(() => resolve('1')))
   const result2 = await new Promise((resolve) => setTimeout(() => resolve('2')))
}
foo()

Note how the promise chain is not built-up in one go. Instead, the promise chain is constructed in stages as control is successively yielded from and returned to the async function. As a result, we must be mindful of error handling behavior when dealing with concurrent asynchronous operations.

For example, in the following code an unhandled promise rejection error will be thrown, even if a .catch handler has been configured further along the promise chain. This is because p2 will not be "wired into" the promise chain until control returns from p1.

async function foo() {
   const p1 = new Promise((resolve) => setTimeout(() => resolve('1'), 1000))
   const p2 = new Promise((_,reject) => setTimeout(() => reject('2'), 500))
   const results = [await p1, await p2] // Do not do this! Use Promise.all or Promise.allSettled instead.
}
foo().catch(() => {}) // Attempt to swallow all errors...

Examples

Async functions and execution order

function resolveAfter2Seconds() {
  console.log("starting slow promise")
  return new Promise(resolve => {
    setTimeout(function() {
      resolve("slow")
      console.log("slow promise is done")
    }, 2000)
  })
}

function resolveAfter1Second() {
  console.log("starting fast promise")
  return new Promise(resolve => {
    setTimeout(function() {
      resolve("fast")
      console.log("fast promise is done")
    }, 1000)
  })
}

async function sequentialStart() {
  console.log('==SEQUENTIAL START==')

  // 1. Execution gets here almost instantly
  const slow = await resolveAfter2Seconds()
  console.log(slow) // 2. this runs 2 seconds after 1.

  const fast = await resolveAfter1Second()
  console.log(fast) // 3. this runs 3 seconds after 1.
}

async function concurrentStart() {
  console.log('==CONCURRENT START with await==');
  const slow = resolveAfter2Seconds() // starts timer immediately
  const fast = resolveAfter1Second() // starts timer immediately

  // 1. Execution gets here almost instantly
  console.log(await slow) // 2. this runs 2 seconds after 1.
  console.log(await fast) // 3. this runs 2 seconds after 1., immediately after 2., since fast is already resolved
}

function concurrentPromise() {
  console.log('==CONCURRENT START with Promise.all==')
  return Promise.all([resolveAfter2Seconds(), resolveAfter1Second()]).then((messages) => {
    console.log(messages[0]) // slow
    console.log(messages[1]) // fast
  })
}

async function parallel() {
  console.log('==PARALLEL with await Promise.all==')

  // Start 2 "jobs" in parallel and wait for both of them to complete
  await Promise.all([
      (async()=>console.log(await resolveAfter2Seconds()))(),
      (async()=>console.log(await resolveAfter1Second()))()
  ])
}

sequentialStart() // after 2 seconds, logs "slow", then after 1 more second, "fast"

// wait above to finish
setTimeout(concurrentStart, 4000) // after 2 seconds, logs "slow" and then "fast"

// wait again
setTimeout(concurrentPromise, 7000) // same as concurrentStart

// wait again
setTimeout(parallel, 10000) // truly parallel: after 1 second, logs "fast", then after 1 more second, "slow"

await and parallelism

In sequentialStart, execution suspends 2 seconds for the first await, and then another second for the second await. The second timer is not created until the first has already fired, so the code finishes after 3 seconds.

In concurrentStart, both timers are created and then awaited. The timers run concurrently, which means the code finishes in 2 rather than 3 seconds, i.e. the slowest timer.
However, the await calls still run in series, which means the second await will wait for the first one to finish. In this case, the result of the fastest timer is processed after the slowest.

If you wish to safely perform two or more jobs in parallel, you must await a call to Promise.all, or Promise.allSettled.

Warning: The functions concurrentStart and concurrentPromise are not functionally equivalent.

In concurrentStart, if promise fast rejects before promise slow is fulfilled, then an unhandled promise rejection error will be raised, regardless of whether the caller has configured a catch clause.

In concurrentPromise, Promise.all wires up the promise chain in one go, meaning that the operation will fail-fast regardless of the order of rejection of the promises, and the error will always occur within the configured promise chain, enabling it to be caught in the normal way.

Rewriting a Promise chain with an async function

An API that returns a Promise will result in a promise chain, and it splits the function into many parts. Consider the following code:

function getProcessedData(url) {
  return downloadData(url) // returns a promise
    .catch(e => {
      return downloadFallbackData(url)  // returns a promise
    })
    .then(v => {
      return processDataInWorker(v)  // returns a promise
    })
}

it can be rewritten with a single async function as follows:

async function getProcessedData(url) {
  let v
  try {
    v = await downloadData(url)
  } catch(e) {
    v = await downloadFallbackData(url)
  }
  return processDataInWorker(v)
}

In the above example, notice there is no await statement after the return keyword, although that would be valid too: The return value of an async function is implicitly wrapped in Promise.resolve - if it's not already a promise itself (as in this example).

Note: The implicit wrapping of return values in Promise.resolve does not imply that return await promiseValue is functionally equivalent to return promiseValue.

Consider the following rewrite of the above code. It returns null if processDataInWorker rejects with an error:

async function getProcessedData(url) {
  let v
  try {
    v = await downloadData(url)
  } catch(e) {
    v = await downloadFallbackData(url)
  }
  try {
    return await processDataInWorker(v)  // Note the `return await` vs. just `return`
  } catch (e) {
    return null
  }
}

Writing return processDataInWorker(v) would have caused the Promise returned by the function to reject, instead of resolving to null if processDataInWorker(v) rejects.

This highlights the subtle difference between return foo; and return await foo;return foo immediately returns foo and never throws, even if foo is a Promise that rejects. return await foo will wait for foo to resolve or reject if it's a Promise, and throws before returning if it rejects.

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-async-function-definitions

async_function

55

15

52

No

42

10.1

55

55

52

42

10.3

6.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/async_function

AsyncFunction

The AsyncFunction creates a new async function object. In JavaScript, every asynchronous function is actually an AsyncFunction object.

Note that AsyncFunction is not a global object. It can be obtained with the following code:

Object.getPrototypeOf(async function(){}).constructor

Syntax

new AsyncFunction(arg0, functionBody)
new AsyncFunction(arg0, arg1, functionBody)
new AsyncFunction(arg0, arg1, ...argN, functionBody)

Parameters

arg1, arg2, ... argN
Names to be used by the function as formal argument names. Each must be a string that corresponds to a valid JavaScript identifier or a list of such strings separated with a comma; for example "x", "theValue", or "a,b".

functionBody
A string containing the JavaScript statements comprising the function definition.

Description

async function objects created with the AsyncFunction constructor are parsed when the function is created. This is less efficient than declaring an async function with an async function expression and calling it within your code, because such functions are parsed with the rest of the code.

All arguments passed to the function are treated as the names of the identifiers of the parameters in the function to be created, in the order in which they are passed.

Note: async functions created with the AsyncFunction constructor do not create closures to their creation contexts; they are always created in the global scope.

When running them, they will only be able to access their own local variables and global ones, not the ones from the scope in which the AsyncFunction constructor was called.

This is different from using eval with code for an async function expression.

Invoking the AsyncFunction constructor as a function (without using the new operator) has the same effect as invoking it as a constructor.

Examples

Creating an async function from an AsyncFunction() constructor

function resolveAfter2Seconds(x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

let AsyncFunction = Object.getPrototypeOf(async function(){}).constructor

let a = new AsyncFunction('a',
                          'b',
                          'return await resolveAfter2Seconds(a) + await resolveAfter2Seconds(b);');

a(10, 20).then(v => {
  console.log(v); // prints 30 after 4 seconds
});

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-async-function-objects

AsyncFunction

55

15

52

No

42

10.1

55

55

52

42

10.3

6.0

See also

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

Symbol.asyncIterator

The Symbol.asyncIterator well-known symbol specifies the default AsyncIterator for an object. If this property is set on an object, it is an async iterable and can be used in a for await...of loop.

Description

The Symbol.asyncIterator symbol is a builtin symbol that is used to access an object's @@asyncIterator method. In order for an object to be async iterable, it must have a Symbol.asyncIterator key.

Property attributes of Symbol.asyncIterator

Writable

no

Enumerable

no

Configurable

no

Examples

User-defined Async Iterables

You can define your own async iterable by setting the [Symbol.asyncIterator] property on an object.

const myAsyncIterable = {
    async* [Symbol.asyncIterator]() {
        yield "hello";
        yield "async";
        yield "iteration!";
    }
};

(async () => {
    for await (const x of myAsyncIterable) {
        console.log(x);
        // expected output:
        //    "hello"
        //    "async"
        //    "iteration!"
    }
})();

When creating an API, remember that async iterables are designed to represent something iterable — like a stream of data or a list —, not to completely replace callbacks and events in most situations.

Built-in Async Iterables

There are currently no built-in JavaScript objects that have the [Symbol.asyncIterator] key set by default. However, WHATWG Streams are set to be the first built-in object to be async iterable, with [Symbol.asyncIterator] recently landing in the spec.

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-symbol.asynciterator

asyncIterator

63

79

57

No

50

11.1

63

63

57

46

No

8.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/Global_Objects/Symbol/asyncIterator

Array.prototype.at()

The at() method takes an integer value and returns the item at that index, allowing for positive and negative integers. Negative integers count back from the last item in the array.

This is not to suggest there is anything wrong with using the square bracket notation. For example array[0] would return the first item. However instead of using array.length for latter items; e.g. array[array.length-1] for the last item, you can call array.at(-1). (See the examples below)

Syntax

at(index)

Parameters

index
The index (position) of the array element to be returned. Supports relative indexing from the end of the array when passed a negative index; i.e. if a negative number is used, the element returned will be found by counting back from the end of the array.

Return value

The element in the array matching the given index. Returns undefined if the given index can not be found.

Examples

Return the last value of an array

The following example provides a function which returns the last element found in a specified array.

// Our array with items
const cart = ['apple', 'banana', 'pear'];

// A function which returns the last item of a given array
function returnLast(arr) {
  return arr.at(-1);
}

// Get the last item of our array 'cart'
const item1 = returnLast(cart);
console.log(item1); // Logs: 'pear'

// Add an item to our 'cart' array
cart.push('orange');
const item2 = returnLast(cart);
console.log(item2); // Logs: 'orange'

Comparing methods

This example compares different ways to select the penultimate (last but one) item of an Array. While all the methods shown below are valid, this example highlights the succinctness and readability of the at() method.

// Our array with items
const colors = ['red', 'green', 'blue'];

// Using length property
const lengthWay = colors[colors.length-2];
console.log(lengthWay); // Logs: 'green'

// Using slice() method. Note an array is returned
const sliceWay = colors.slice(-2, -1);
console.log(sliceWay[0]); // Logs: 'green'

// Using at() method
const atWay = colors.at(-2);
console.log(atWay); // Logs: 'green'

Math.atan()

The Math.atan() function returns the arctangent (in radians) of a number, that is

$$\mathtt{\operatorname{Math.atan}(x)} = \arctan(x) = \text{the\ unique}\; y \in \left\lbrack {- \frac{\pi}{2};\frac{\pi}{2}} \right\rbrack\,\text{such\ that}\;\tan(y) = x$$

Syntax

Math.atan(x)

Parameters

x
A number.

Return value

The arctangent (in radians) of the given number.

Description

The Math.atan() method returns a numeric value between $- \frac{\pi}{2}$ and $\frac{\pi}{2}$ radians.

Because atan() is a static method of Math, you always use it as Math.atan(), rather than as a method of a Math object you created (Math is not a constructor).

Examples

Using Math.atan()

Math.atan(1);   // 0.7853981633974483
Math.atan(0);   // 0
Math.atan(-0);  // -0

Math.atan(Infinity);   //  1.5707963267948966
Math.atan(-Infinity);  // -1.5707963267948966

// The angle that the line [(0,0);(x,y)] forms with the x-axis in a Cartesian coordinate system
Math.atan(y / x);

Note that you may want to avoid using ±Infinity for stylistic reasons. In this case, Math.atan2() with 0 as the second argument may be a better solution.

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-math.atan

atan

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/Global_Objects/Math/atan

Math.atan2()

The Math.atan2() function returns the angle in the plane (in radians) between the positive x-axis and the ray from (0,0) to the point (x,y), for Math.atan2(y,x).

Syntax

Math.atan2(y, x)

Parameters

y
The y coordinate of the point.

x
The x coordinate of the point

Return value

The angle in radians (in [ − π, π]) between the positive x-axis and the ray from (0,0) to the point (x,y).

Description

The Math.atan2() method returns a numeric value between -π and π representing the angle theta of an (x, y) point. This is the counterclockwise angle, measured in radians, between the positive X axis, and the point (x, y). Note that the arguments to this function pass the y-coordinate first and the x-coordinate second.

A simple diagram showing the angle returned by atan2(y, x)

Math.atan2() is passed separate x and y arguments, and Math.atan() is passed the ratio of those two arguments.

Because atan2() is a static method of Math, you always use it as Math.atan2(), rather than as a method of a Math object you created (Math is not a constructor).

Examples

Using Math.atan2()

Math.atan2(90, 15); // 1.4056476493802699
Math.atan2(15, 90); // 0.16514867741462683

Math.atan2(±0, -0);               // ±PI.
Math.atan2(±0, +0);               // ±0.
Math.atan2(±0, -x);               // ±PI for x > 0.
Math.atan2(±0, x);                // ±0 for x > 0.
Math.atan2(-y, ±0);               // -PI/2 for y > 0.
Math.atan2(y, ±0);                // PI/2 for y > 0.
Math.atan2(±y, -Infinity);        // ±PI for finite y > 0.
Math.atan2(±y, +Infinity);        // ±0 for finite y > 0.
Math.atan2(±Infinity, x);         // ±PI/2 for finite x.
Math.atan2(±Infinity, -Infinity); // ±3*PI/4.
Math.atan2(±Infinity, +Infinity); // ±PI/4.

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-math.atan2

atan2

1

12

1

4

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/Global_Objects/Math/atan2

Math.atanh()

The Math.atanh() function returns the hyperbolic arctangent of a number, that is

x ∈ (−1,1), Math.atanh(``x``) = arctanh (x) = the unique y such that tanh (y) = x

Syntax

Math.atanh(x)

Parameters

x
A number.

Return value

The hyperbolic arctangent of the given number.

Description

Because atanh() is a static method of Math, you always use it as Math.atanh(), rather than as a method of a Math object you created (Math is not a constructor).

Examples

Using Math.atanh()

Math.atanh(-2);  // NaN
Math.atanh(-1);  // -Infinity
Math.atanh(0);   // 0
Math.atanh(0.5); // 0.5493061443340548
Math.atanh(1);   // Infinity
Math.atanh(2);   // NaN

For values greater than 1 or less than -1, NaN is returned.

Polyfill

For |x| < 1, we have $\operatorname{artanh}(x) = \frac{1}{2}\ln\left( \frac{1 + x}{1 - x} \right)$ so this can be emulated by the following function:

Math.atanh = Math.atanh || function(x) {
  return Math.log((1+x)/(1-x)) / 2;
};

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-math.atanh

atanh

38

12

25

No

25

8

38

38

25

25

8

3.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/Global_Objects/Math/atanh

Atomics

The Atomics object provides atomic operations as static methods. They are used with SharedArrayBuffer and ArrayBuffer objects.

Description

The Atomic operations are installed on an Atomics module. Unlike the other global objects, Atomics is not a constructor. You cannot use it with a new operator or invoke the Atomics object as a function. All properties and methods of Atomics are static (as is the case with the Math object, for example).

Atomic operations

When memory is shared, multiple threads can read and write the same data in memory. Atomic operations make sure that predictable values are written and read, that operations are finished before the next operation starts and that operations are not interrupted.

Wait and notify

The wait() and notify() methods are modeled on Linux futexes ("fast user-space mutex") and provide ways for waiting until a certain condition becomes true and are typically used as blocking constructs.

Static methods

Atomics.add()
Adds the provided value to the existing value at the specified index of the array. Returns the old value at that index.

Atomics.and()
Computes a bitwise AND on the value at the specified index of the array with the provided value. Returns the old value at that index.

Atomics.compareExchange()
Stores a value at the specified index of the array, if it equals a value. Returns the old value.

Atomics.exchange()
Stores a value at the specified index of the array. Returns the old value.

Atomics.isLockFree(size)
An optimization primitive that can be used to determine whether to use locks or atomic operations. Returns true if an atomic operation on arrays of the given element size will be implemented using a hardware atomic operation (as opposed to a lock). Experts only.

Atomics.load()
Returns the value at the specified index of the array.

Atomics.notify()
Notifies agents that are waiting on the specified index of the array. Returns the number of agents that were notified.

Atomics.or()
Computes a bitwise OR on the value at the specified index of the array with the provided value. Returns the old value at that index.

Atomics.store()
Stores a value at the specified index of the array. Returns the value.

Atomics.sub()
Subtracts a value at the specified index of the array. Returns the old value at that index.

Atomics.wait()
Verifies that the specified index of the array still contains a value and sleeps awaiting or times out. Returns either "ok", "not-equal", or "timed-out". If waiting is not allowed in the calling agent then it throws an Error exception. (Most browsers will not allow wait() on the browser's main thread.)

Atomics.xor()
Computes a bitwise XOR on the value at the specified index of the array with the provided value. Returns the old value at that index.

Examples

Using Atomics

const sab = new SharedArrayBuffer(1024);
const ta = new Uint8Array(sab);

ta[0]; // 0
ta[0] = 5; // 5

Atomics.add(ta, 0, 12); // 5
Atomics.load(ta, 0); // 17

Atomics.and(ta, 0, 1); // 17
Atomics.load(ta, 0); // 1

Atomics.compareExchange(ta, 0, 5, 12); // 1
Atomics.load(ta, 0); // 1

Atomics.exchange(ta, 0, 12); // 1
Atomics.load(ta, 0); // 12

Atomics.isLockFree(1); // true
Atomics.isLockFree(2); // true
Atomics.isLockFree(3); // false
Atomics.isLockFree(4); // true

Atomics.or(ta, 0, 1); // 12
Atomics.load(ta, 0);  // 13

Atomics.store(ta, 0, 12); // 12

Atomics.sub(ta, 0, 2); // 12
Atomics.load(ta, 0); // 10

Atomics.xor(ta, 0, 1); // 10
Atomics.load(ta, 0); // 11

Waiting and notifiying

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-object

Atomics

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.

Atomic_operations_on_non-shared_buffers

No

No

79

No

No

No

No

No

79

No

No

No

add

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.

and

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.

compareExchange

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.

exchange

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.

isLockFree

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.

load

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.

notify

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

78

63

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

57

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

55-57

48-55

46-48

The count parameter defaults to 0 instead of the later-specified +Infinity.

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.

63

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

57

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

55-57

48-55

46-48

The count parameter defaults to 0 instead of the later-specified +Infinity.

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.

or

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.

store

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.

sub

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.

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.

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

await

The await operator is used to wait for a Promise. It can only be used inside an async function within regular JavaScript code; however it can be used on its own with JavaScript modules.

Syntax

[rv] = await expression;

expression
A Promise or any value to wait for.

rv
Returns the fulfilled value of the promise, or the value itself if it's not a Promise.

Description

The await expression causes async function execution to pause until a Promise is settled (that is, fulfilled or rejected), and to resume execution of the async function after fulfillment. When resumed, the value of the await expression is that of the fulfilled Promise.

If the Promise is rejected, the await expression throws the rejected value.

If the value of the expression following the await operator is not a Promise, it's converted to a resolved Promise.

An await splits execution flow, allowing the caller of the async function to resume execution. After the await defers the continuation of the async function, execution of subsequent statements ensues. If this await is the last expression executed by its function, execution continues by returning to the function's caller a pending Promise for completion of the await's function and resuming execution of that caller.

Examples

Awaiting a promise to be fulfilled

If a Promise is passed to an await expression, it waits for the Promise to be fulfilled and returns the fulfilled value.

function resolveAfter2Seconds(x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

async function f1() {
  var x = await resolveAfter2Seconds(10);
  console.log(x); // 10
}

f1();

Thenable objects

Thenable objects will be fulfilled just the same.

async function f2() {
  const thenable = {
    then: function(resolve, _reject) {
      resolve('resolved!')
    }
  };
  console.log(await thenable); // resolved!
}

f2();

Conversion to promise

If the value is not a Promise, it converts the value to a resolved Promise, and waits for it.

async function f3() {
  var y = await 20;
  console.log(y); // 20
}

f3();

Promise rejection

If the Promise is rejected, the rejected value is thrown.

async function f4() {
  try {
    var z = await Promise.reject(30);
  } catch(e) {
    console.error(e); // 30
  }
}

f4();

Handling rejected promises

Handle rejected Promise without try block.

var response = await promisedFunction().catch((err) => { console.error(err); });
// response will be undefined if the promise is rejected

Top level await

You can use the await keyword on its own (outside of an async function) within a JavaScript module. This means modules, with child modules that use await, wait for the child module to execute before they themselves run. All while not blocking other child modules from loading.

Here is an example of a simple module using the Fetch API and specifying await within the export statement. Any modules that include this will wait for the fetch to resolve before running any code.

// fetch request
const colors = fetch('../data/colors.json')
  .then(response => response.json());

export default await colors;

Warning: 08/09 is not a legal ECMA-262 octal constant

The JavaScript warning "08 (or 09) is not a legal ECMA-262 octal constant" occurs when 08 or 09 number literals are used. They can't be interpreted as an octal number.

Message

Warning: SyntaxError: 08 is not a legal ECMA-262 octal constant.
Warning: SyntaxError: 09 is not a legal ECMA-262 octal constant.

Error type

Warning. JavaScript execution won't be halted.

What went wrong?

Decimal literals can start with a zero (0) followed by another decimal digit, but If all digits after the leading 0 are smaller than 8, the number is interpreted as an octal number. Because this is not the case with 08 and 09, JavaScript warns about it.

Note that octal literals and octal escape sequences are deprecated and will present an additional deprecation warning. With ECMAScript 6 and later, the syntax uses a leading zero followed by a lowercase or uppercase Latin letter "O" (0o or 0O). See the page about lexical grammar for more information.

Examples

Invalid octal numbers

08;
09;
// SyntaxError: 08 is not a legal ECMA-262 octal constant
// SyntaxError: "0"-prefixed octal literals and octal escape sequences
// are deprecated

Valid octal numbers

Use a leading zero followed by the letter "o";

0O755;
0o644;

See also

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

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: invalid argument (Edge)
RangeError: radix must be an integer at least 2 and no greater than 36 (Firefox)
RangeError: toString() radix argument must be between 2 and 36 (Chrome)

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:

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

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

SyntaxError: invalid regular expression flag "x"

The JavaScript exception "invalid regular expression flag" occurs when the flags, defined after the second slash in regular expression literal, are not one of g, i, m, s, u, or y.

Message

SyntaxError: Syntax error in regular expression (Edge)
SyntaxError: invalid regular expression flag "x" (Firefox)
SyntaxError: Invalid regular expression flags (Chrome)

Error type

SyntaxError

What went wrong?

There are invalid regular expression flags in the code. In a regular expression literal, which consists of a pattern enclosed between slashes, the flags are defined after the second slash. They can also be defined in the constructor function of the RegExp object (second parameter). Regular expression flags can be used separately or together in any order, but there are only six of them in ECMAScript.

To include a flag with the regular expression, use this syntax:

var re = /pattern/flags;

or

var re = new RegExp('pattern', 'flags');
Regular expression flags
Flag Description
g Global search.
i Case-insensitive search.
m Multi-line search.
s Allow . to match newlines (added in ECMAScript 2018)
u Unicode; treat pattern as a sequence of Unicode code points
y Perform a "sticky" search that matches starting at the current position in the target string. See sticky

Examples

There are only six valid regular expression flags.

/foo/bar;

// SyntaxError: invalid regular expression flag "b"

Did you intend to create a regular expression? An expression containing two slashes is interpreted as a regular expression literal.

let obj = {
  url: /docs/Web
};

// SyntaxError: invalid regular expression flag "W"

Or did you mean to create a string instead? Add single or double quotes to create a string literal.

let obj = {
  url: '/docs/Web'
};

Valid regular expression flags

See the table above for the six valid regular expression flags that are allowed in JavaScript.

/foo/g;
/foo/gims;
/foo/uy;

See also

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

SyntaxError: return not in function

The JavaScript exception "return (or yield) not in function" occurs when a return or yield statement is called outside of a function.

Message

SyntaxError: 'return' statement outside of function (Edge)
SyntaxError: return not in function (Firefox)
SyntaxError: yield not in function (Firefox)

Error type

SyntaxError.

What went wrong?

A return or yield statement is called outside of a function. Maybe there are missing curly brackets somewhere? The return and yield statements must be in a function, because they end (or pause and resume) function execution and specify a value to be returned to the function caller.

Examples

Missing curly brackets

var cheer = function(score) {
  if (score === 147)
    return 'Maximum!';
  };
  if (score > 100) {
    return 'Century!';
  }
}

// SyntaxError: return not in function

The curly brackets look correct at a first glance, but this code snippet is missing a { after the first if statement. Correct would be:

var cheer = function(score) {
  if (score === 147) {
    return 'Maximum!';
  }
  if (score > 100) {
    return 'Century!';
  }
};

See also

  • return
  • yield

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

Intl.Locale.prototype.baseName

The Intl.Locale.prototype.baseName property returns a substring of the Locale's string representation, containing core information about the Locale.

Description

An Intl.Locale object represents a parsed local and options for that locale. The baseName property returns basic, core information about the Locale in the form of a substring of the complete data string. Specifically, the property returns the substring containing the language, and the script and region if available.

baseName returns the language ["-" script] ["-" region] *("-" variant) subsequence of the unicode_language_id grammar.

Examples

Basic Example

let myLoc = new Intl.Locale("fr-Latn-CA"); // Sets locale to Canadian French
console.log(myLoc.toString()); // Prints out "fr-Latn-CA-u-ca-gregory"
console.log(myLoc.baseName); // Prints out "fr-Latn-CA"

Example with options in the input string

// Sets language to Japanese, region to Japan,

// calendar to Gregorian, hour cycle to 24 hours
let japan = new Intl.Locale("ja-JP-u-ca-gregory-hc-24");
console.log(japan.toString()); // Prints out "ja-JP-u-ca-gregory-hc-h24"
console.log(japan.baseName); // Prints out "ja-JP"

Example with options that override input string

// Input string indicates language as Dutch and region as Belgium,

// but options object overrides the region and sets it to the Netherlands
let dutch = new Intl.Locale("nl-Latn-BE", {region: "NL"});

console.log(dutch.baseName); // Prints out "nl-Latn-NL"

Specifications

Specification
ECMAScript Internationalization API Specification (ECMAScript Internationalization API)

#sec-Intl.Locale.prototype.baseName

baseName

74

79

75

No

62

14

74

74

79

53

14

11.0

See also

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/baseName

String.prototype.big()

Deprecated

This feature is no longer recommended. Though some browsers might still support it, it may have already been removed from the relevant web standards, may be in the process of being dropped, or may only be kept for compatibility purposes. Avoid using it, and update existing code if possible; see the compatibility table at the bottom of this page to guide your decision. Be aware that this feature may cease to work at any time.

The big() method creates a <big> HTML element that causes a string to be displayed in a big font.

Note: The <big> element has been removed in HTML5 and shouldn't be used anymore. Instead web developers should use CSS properties.

Syntax

big()

Return value

A string containing a <big> HTML element.

Description

The big() method embeds a string in a <big> element: "<big>str</big>".

Examples

Using big()

The following example uses string methods to change the size of a string:

var worldString = 'Hello, world';

console.log(worldString.small());     // <small>Hello, world</small>
console.log(worldString.big());       // <big>Hello, world</big>
console.log(worldString.fontsize(7)); // <font size="7">Hello, world</font>

With the element.style object you can get the element's style attribute and manipulate it more generically, for example:

document.getElementById('yourElemId').style.fontSize = '2em';

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-string.prototype.big

big

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/Global_Objects/String/big

BigInt

BigInt is a built-in object whose constructor returns a bigint primitive — also called a BigInt value, or sometimes just a BigInt — to represent whole numbers larger than 253 - 1 (Number.MAX_SAFE_INTEGER), which is the largest number JavaScript can represent with a number primitive (or Number value). BigInt values can be used for arbitrarily large integers.

Description

A BigInt value, also sometimes just called a BigInt, is a bigint primitive, created by appending n to the end of an integer literal, or by calling the BigInt() constructor (but without the new operator) and giving it an integer value or string value.

const previouslyMaxSafeInteger = 9007199254740991n

const alsoHuge = BigInt(9007199254740991)
// ↪ 9007199254740991n

const hugeString = BigInt("9007199254740991")
// ↪ 9007199254740991n

const hugeHex = BigInt("0x1fffffffffffff")
// ↪ 9007199254740991n

const hugeOctal = BigInt("0o377777777777777777")
// ↪ 9007199254740991n

const hugeBin = BigInt("0b11111111111111111111111111111111111111111111111111111")
// ↪ 9007199254740991n

BigInt values are similar to Number values in some ways, but also differ in a few key matters: A BigInt value cannot be used with methods in the built-in Math object and cannot be mixed with a Number value in operations; they must be coerced to the same type. Be careful coercing values back and forth, however, as the precision of a BigInt value may be lost when it is coerced to a Number value.

Type information

When tested against typeof, a BigInt value (bigint primitive) will give "bigint":

typeof 1n === 'bigint'           // true
typeof BigInt('1') === 'bigint'  // true

A BigInt value can also be wrapped in an Object:

typeof Object(1n) === 'object'  // true

Operators

The following operators may be used with BigInt values or object-wrapped BigInt values:

+ * - % **

Bitwise operators are supported as well, except >>> (zero-fill right shift), as every BigInt value is signed.

Also unsupported is the unary operator (+), in order to not break asm.js.

const previousMaxSafe = BigInt(Number.MAX_SAFE_INTEGER)
// ↪ 9007199254740991n

const maxPlusOne = previousMaxSafe + 1n
// ↪ 9007199254740992n

const theFuture = previousMaxSafe + 2n
// ↪ 9007199254740993n, this works now!

const multi = previousMaxSafe * 2n
// ↪ 18014398509481982n

const subtr = multi – 10n
// ↪ 18014398509481972n

const mod = multi % 10n
// ↪ 2n

const bigN = 2n ** 54n
// ↪ 18014398509481984n

bigN * -1n
// ↪ –18014398509481984n

The / operator also works as expected with whole numbers — but operations with a fractional result will be truncated when used with a BigInt value — they won't return any fractional digits.

const expected = 4n / 2n
// ↪ 2n

const truncated = 5n / 2n
// ↪ 2n, not 2.5n

Comparisons

A BigInt value is not strictly equal to a Number value, but it is loosely so:

0n === 0
// ↪ false

0n == 0
// ↪ true

A Number value and a BigInt value may be compared as usual:

1n < 2
// ↪ true

2n > 1
// ↪ true

2 > 2
// ↪ false

2n > 2
// ↪ false

2n >= 2
// ↪ true

BigInt values and Number values may be mixed in arrays and sorted:

const mixed = [4n, 6, -12n, 10, 4, 0, 0n]
// ↪  [4n, 6, -12n, 10, 4, 0, 0n]

mixed.sort() // default sorting behavior
// ↪  [ -12n, 0, 0n, 10, 4n, 4, 6 ]

mixed.sort((a, b) => a - b)
// won't work since subtraction will not work with mixed types
// TypeError: can't convert BigInt value to Number value

// sort with an appropriate numeric comparator
mixed.sort((a, b) => (a < b) ? -1 : ((a > b) ? 1 : 0))
// ↪  [ -12n, 0, 0n, 4n, 4, 6, 10 ]

Note that comparisons with Object-wrapped BigInt values act as with other objects, only indicating equality when the same object instance is compared:

0n === Object(0n)          // false
Object(0n) === Object(0n)  // false

const o = Object(0n)
o === o                    // true

Conditionals

A BigInt value behaves like a Number value in cases where:

if (0n) {
  console.log('Hello from the if!')
} else {
  console.log('Hello from the else!')
}

// ↪ "Hello from the else!"

0n || 12n
// ↪ 12n

0n && 12n
// ↪ 0n

Boolean(0n)
// ↪ false

Boolean(12n)
// ↪ true

!12n
// ↪ false

!0n
// ↪ true

Constructor

BigInt()
Creates a new BigInt value.

Static methods

BigInt.asIntN()
Clamps a BigInt value to a signed integer value, and returns that value.

BigInt.asUintN()
Clamps a BigInt value to an unsigned integer value, and returns that value.

Instance methods

BigInt.prototype.toLocaleString()
Returns a string with a language-sensitive representation of this BigInt value. Overrides the Object.prototype.toLocaleString() method.

BigInt.prototype.toString()
Returns a string representing this BigInt value in the specified radix (base). Overrides the Object.prototype.toString() method.

BigInt.prototype.valueOf()
Returns this BigInt value. Overrides the Object.prototype.valueOf() method.

Usage recommendations

Coercion

Because coercing between Number values and BigInt values can lead to loss of precision, the following are recommended:

  • Only use a BigInt value when values greater than 253 are reasonably expected.
  • Don't coerce between BigInt values and Number values.

Cryptography

The operations supported on BigInt values are not constant-time. BigInt values are therefore unsuitable for use in cryptography.

Use within JSON

Using JSON.stringify() with any BigInt value will raise a TypeError, as BigInt values aren't serialized in JSON by default. However, you can implement your own toJSON method:

BigInt.prototype.toJSON = function() { return this.toString()  }

Instead of throwing, JSON.stringify now produces a string like this:

JSON.stringify(BigInt(1))
// '"1"'

Examples

Calculating Primes

// Returns true if the passed BigInt value is a prime number
function isPrime(p) {
  for (let i = 2n; i * i <= p; i++) {
    if (p % i === 0n) return false;
  }
  return true
}

// Takes a BigInt value as an argument, returns nth prime number as a BigInt value
function nthPrime(nth) {
  let maybePrime = 2n
  let prime = 0n

  while (nth >= 0n) {
    if (isPrime(maybePrime)) {
      nth--
      prime = maybePrime
    }
    maybePrime++
  }

  return prime
}

nthPrime(20n)
// ↪ 73n

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-bigint-objects

BigInt

67

79

68

No

54

14

67

67

68

48

14

9.0

BigInt

67

79

68

No

54

14

67

67

68

48

14

9.0

asIntN

67

79

68

No

54

14

67

67

68

48

14

9.0

asUintN

67

79

68

No

54

14

67

67

68

48

14

9.0

toLocaleString

67

79

68

No

54

14

67

67

68

48

14

9.0

toString

67

79

68

No

54

14

67

67

68

48

14

9.0

valueOf

67

79

68

No

54

14

67

67

68

48

14

9.0

See also

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

BigInt64Array

The BigInt64Array typed array represents an array of 64-bit signed integers in the platform byte order. If control over byte order is needed, use DataView instead. The contents are initialized to 0n. Once established, you can reference elements in the array using the object's methods, or by using standard array index syntax (that is, using bracket notation).

Constructor

BigInt64Array()
Creates a new BigInt64Array object.

Static properties

BigInt64Array.BYTES_PER_ELEMENT
Returns a number value of the element size. 8 in the case of a BigInt64Array.

BigInt64Array.name
Returns the string value of the constructor name. In the case of the BigInt64Array type, this is "BigInt64Array".

Static methods

BigInt64Array.from()
Creates a new BigInt64Array from an array-like or iterable object. See also Array.from().

BigInt64Array.of()
Creates a new BigInt64Array with a variable number of arguments. See also Array.of().

Instance properties

BigInt64Array.prototype.buffer
Returns the ArrayBuffer referenced by the BigInt64Array. This is fixed at construction time and thus read only.

BigInt64Array.prototype.byteLength
Returns the length (in bytes) of the BigInt64Array from the start of its ArrayBuffer. This is fixed at construction time and thus read only.

BigInt64Array.prototype.byteOffset
Returns the offset (in bytes) of the BigInt64Array from the start of its ArrayBuffer. This is fixed at construction time and thus read only.

BigInt64Array.prototype.length
Returns the number of elements hold in the BigInt64Array. This is fixed at construction time and thus read only.

Instance methods

BigInt64Array.prototype.copyWithin()
Copies a sequence of array elements within the array. See also Array.prototype.copyWithin().

BigInt64Array.prototype.entries()
Returns a new Array Iterator object that contains the key/value pairs for each index in the array. See also Array.prototype.entries().

BigInt64Array.prototype.every()
Tests whether all elements in the array pass the test provided by a function. See also Array.prototype.every().

BigInt64Array.prototype.fill()
Fills all the elements of an array from a start index to an end index with a static value. See also Array.prototype.fill().

BigInt64Array.prototype.filter()
Creates a new array with all of the elements of this array for which the provided filtering function returns true. See also Array.prototype.filter().

BigInt64Array.prototype.find()
Returns the found value in the array if an element in the array satisfies the provided testing function, or undefined if not found. See also Array.prototype.find().

BigInt64Array.prototype.findIndex()
Returns the found index in the array if an element in the array satisfies the provided testing function, or -1 if not found. See also Array.prototype.findIndex().

BigInt64Array.prototype.forEach()
Calls a function for each element in the array. See also Array.prototype.forEach().

BigInt64Array.prototype.includes()
Determines whether a typed array includes a certain element, returning true or false as appropriate. See also Array.prototype.includes().

BigInt64Array.prototype.indexOf()
Returns the first (least) index of an element within the array equal to the specified value, or -1 if none is found. See also Array.prototype.indexOf().

BigInt64Array.prototype.join()
Joins all elements of an array into a string. See also Array.prototype.join().

BigInt64Array.prototype.keys()
Returns a new Array Iterator that contains the keys for each index in the array. See also Array.prototype.keys().

BigInt64Array.prototype.lastIndexOf()
Returns the last (greatest) index of an element within the array equal to the specified value, or -1 if none is found. See also Array.prototype.lastIndexOf().

BigInt64Array.prototype.map()
Creates a new array with the results of calling a provided function on every element in this array. See also Array.prototype.map().

BigInt64Array.prototype.reduce()
Applies a function against an accumulator and each value of the array (from left-to-right) so as to reduce it to a single value. See also Array.prototype.reduce().

BigInt64Array.prototype.reduceRight()
Applies a function against an accumulator and each value of the array (from right-to-left) so as to reduce it to a single value. See also Array.prototype.reduceRight().

BigInt64Array.prototype.reverse()
Reverses the order of the elements of an array — the first becomes the last, and the last becomes the first. See also Array.prototype.reverse().

BigInt64Array.prototype.set()
Stores multiple values in the typed array, reading input values from a specified array.

BigInt64Array.prototype.slice()
Extracts a section of an array and returns a new array. See also Array.prototype.slice().

BigInt64Array.prototype.some()
Returns true if at least one element in this array satisfies the provided testing function. See also Array.prototype.some().

BigInt64Array.prototype.sort()
Sorts the elements of an array in place and returns the array. See also Array.prototype.sort().

BigInt64Array.prototype.subarray()
Returns a new BigUint64Array from the given start and end element index.

BigInt64Array.prototype.values()
Returns a new Array Iterator object that contains the values for each index in the array. See also Array.prototype.values().

BigInt64Array.prototype.toLocaleString()
Returns a localized string representing the array and its elements. See also Array.prototype.toLocaleString().

BigInt64Array.prototype.toString()
Returns a string representing the array and its elements. See also Array.prototype.toString().

BigInt64Array.prototype[@@iterator]()
Returns a new Array Iterator object that contains the values for each index in the array.

Examples

Different ways to create a BigInt64Array

// From a length
var bigint64 = new BigInt64Array(2);
bigint64[0] = 42n;
console.log(bigint64[0]); // 42n
console.log(bigint64.length); // 2
console.log(bigint64.BYTES_PER_ELEMENT); // 8

// From an array
var arr = new BigInt64Array([21n,31n]);
console.log(arr[1]); // 31n

// From another TypedArray
var x = new BigInt64Array([21n, 31n]);
var y = new BigInt64Array(x);
console.log(y[0]); // 21n

// From an ArrayBuffer
var buffer = new ArrayBuffer(32);
var z = new BigInt64Array(buffer, 0, 4);

// From an iterable
var iterable = function*(){ yield* [1n, 2n, 3n]; }();
var bigint64 = new BigInt64Array(iterable);
// BigInt64Array[1n, 2n, 3n]

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-typedarray-objects

BigInt64Array

67

79

68

No

54

No

67

67

68

48

No

9.0

BigInt64Array

67

79

68

No

54

No

67

67

68

48

No

9.0

See also

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

BigUint64Array

The BigUint64Array typed array represents an array of 64-bit unsigned integers in the platform byte order. If control over byte order is needed, use DataView instead. The contents are initialized to 0n. Once established, you can reference elements in the array using the object's methods, or by using standard array index syntax (that is, using bracket notation).

Constructor

BigUint64Array()
Creates a new BigUint64Array object.

Static properties

BigUint64Array.BYTES_PER_ELEMENT
Returns a number value of the element size. 8 in the case of a BigUint64Array.

BigUint64Array.name
Returns the string value of the constructor name. In the case of the BigUint64Array type this is "BigUint64Array".

Static methods

BigUint64Array.from()
Creates a new BigUint64Array from an array-like or iterable object. See also Array.from().

BigUint64Array.of()
Creates a new BigUint64Array with a variable number of arguments. See also Array.of().

Instance properties

BigUint64Array.prototype.buffer
Returns the ArrayBuffer referenced by the BigUint64Array. This is fixed at construction time and thus read only.

BigUint64Array.prototype.byteLength
Returns the length (in bytes) of the BigUint64Array from the start of its ArrayBuffer. This is fixed at construction time and thus read only.

BigUint64Array.prototype.byteOffset
Returns the offset (in bytes) of the BigUint64Array from the start of its ArrayBuffer. This is fixed at construction time and thus read only.

BigUint64Array.prototype.length
Returns the number of elements hold in the BigUint64Array. This is fixed at construction time and thus read only.

Instance methods

BigUint64Array.prototype.copyWithin()
Copies a sequence of array elements within the array. See also Array.prototype.copyWithin().

BigUint64Array.prototype.entries()
Returns a new Array Iterator object that contains the key/value pairs for each index in the array. See also Array.prototype.entries().

BigUint64Array.prototype.every()
Tests whether all elements in the array pass the test provided by a function. See also Array.prototype.every().

BigUint64Array.prototype.fill()
Fills all the elements of an array from a start index to an end index with a static value. See also Array.prototype.fill().

BigUint64Array.prototype.filter()
Creates a new array with all of the elements of this array for which the provided filtering function returns true. See also Array.prototype.filter().

BigUint64Array.prototype.find()
Returns the found value in the array if an element in the array satisfies the provided testing function, or undefined if not found. See also Array.prototype.find().

BigUint64Array.prototype.findIndex()
Returns the found index in the array if an element in the array satisfies the provided testing function, or -1 if not found. See also Array.prototype.findIndex().

BigUint64Array.prototype.forEach()
Calls a function for each element in the array. See also Array.prototype.forEach().

BigUint64Array.prototype.includes()
Determines whether a typed array includes a certain element, returning true or false as appropriate. See also Array.prototype.includes().

BigUint64Array.prototype.indexOf()
Returns the first (least) index of an element within the array equal to the specified value, or -1 if none is found. See also Array.prototype.indexOf().

BigUint64Array.prototype.join()
Joins all elements of an array into a string. See also Array.prototype.join().

BigUint64Array.prototype.keys()
Returns a new Array Iterator that contains the keys for each index in the array. See also Array.prototype.keys().

BigUint64Array.prototype.lastIndexOf()
Returns the last (greatest) index of an element within the array equal to the specified value, or -1 if none is found. See also Array.prototype.lastIndexOf().

BigUint64Array.prototype.map()
Creates a new array with the results of calling a provided function on every element in this array. See also Array.prototype.map().

BigUint64Array.prototype.reduce()
Apply a function against an accumulator and each value of the array (from left-to-right) so as to reduce it to a single value. See also Array.prototype.reduce().

BigUint64Array.prototype.reduceRight()
Applies a function against an accumulator and each value of the array (from right-to-left) so as to reduce it to a single value. See also Array.prototype.reduceRight().

BigUint64Array.prototype.reverse()
Reverses the order of the elements of an array — the first becomes the last, and the last becomes the first. See also Array.prototype.reverse().

BigUint64Array.prototype.set()
Stores multiple values in the typed array, reading input values from a specified array.

BigUint64Array.prototype.slice()
Extracts a section of an array and returns a new array. See also Array.prototype.slice().

BigUint64Array.prototype.some()
Returns true if at least one element in this array satisfies the provided testing function. See also Array.prototype.some().

BigUint64Array.prototype.sort()
Sorts the elements of an array in place and returns the array. See also Array.prototype.sort().

BigUint64Array.prototype.subarray()
Returns a new BigUint64Array from the given start and end element index.

BigUint64Array.prototype.values()
Returns a new Array Iterator object that contains the values for each index in the array. See also Array.prototype.values().

BigUint64Array.prototype.toLocaleString()
Returns a localized string representing the array and its elements. See also Array.prototype.toLocaleString().

BigUint64Array.prototype.toString()
Returns a string representing the array and its elements. See also Array.prototype.toString().

BigUint64Array.prototype[@@iterator]()
Returns a new Array Iterator object that contains the values for each index in the array.

Examples

Different ways to create a BigUint64Array

// From a length
var biguint64 = new BigUint64Array(2);
biguint64[0] = 42n;
console.log(biguint64[0]); // 42n
console.log(biguint64.length); // 2
console.log(biguint64.BYTES_PER_ELEMENT); // 8

// From an array
var arr = new BigUint64Array([21n,31n]);
console.log(arr[1]); // 31n

// From another TypedArray
var x = new BigUint64Array([21n, 31n]);
var y = new BigUint64Array(x);
console.log(y[0]); // 21n

// From an ArrayBuffer
var buffer = new ArrayBuffer(32);
var z = new BigUint64Array(buffer, 0, 4);

// From an iterable
var iterable = function*(){ yield* [1n, 2n, 3n]; }();
var biguint64 = new BigUint64Array(iterable);
// BigUint64Array[1n, 2n, 3n]

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-typedarray-objects

BigUint64Array

67

79

68

No

54

No

67

67

68

48

No

9.0

BigUint64Array

67

79

68

No

54

No

67

67

68

48

No

9.0

See also

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

Function.prototype.bind()

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

Syntax

bind(thisArg)
bind(thisArg, arg1)
bind(thisArg, arg1, arg2)
bind(thisArg, arg1, ... , argN)

Parameters

thisArg
The value to be passed as the this parameter to the target function func when the bound function is called. The value is ignored if the bound function is constructed using the new operator. When using bind to create a function (supplied as a callback) inside a setTimeout, any primitive value passed as thisArg is converted to object. If no arguments are provided to bind , or if the thisArg is null or undefined, the this of the executing scope is treated as the thisArg for the new function.

arg1, arg2, ...argN Optional
Arguments to prepend to arguments provided to the bound function when invoking func.

Return value

A copy of the given function with the specified this value, and initial arguments (if provided).

Description

The bind() function creates a new bound function, which is an exotic function object (a term from ECMAScript 2015) that wraps the original function object. Calling the bound function generally results in the execution of its wrapped function.

A bound function has the following internal properties:

[[BoundTargetFunction]]
The wrapped function object

[[BoundThis]]
The value that is always passed as this value when calling the wrapped function.

[[BoundArguments]]
A list of values whose elements are used as the first arguments to any call to the wrapped function.

[[Call]]
Executes code associated with this object. Invoked via a function call expression. The arguments to the internal method are a this value and a list containing the arguments passed to the function by a call expression.

When a bound function is called, it calls internal method [[Call]] on [[BoundTargetFunction]], with following arguments Call(boundThis, ...args). Where boundThis is [[BoundThis]], args is [[BoundArguments]], followed by the arguments passed by the function call.

A bound function may also be constructed using the new operator. Doing so acts as though the target function had instead been constructed. The provided this value is ignored, while prepended arguments are provided to the emulated function.

Examples

Creating a bound function

The simplest use of bind() is to make a function that, no matter how it is called, is called with a particular this value.

A common mistake for new JavaScript programmers is to extract a method from an object, then to later call that function and expect it to use the original object as its this (e.g., by using the method in callback-based code).

Without special care, however, the original object is usually lost. Creating a bound function from the function, using the original object, neatly solves this problem:

this.x = 9;    // 'this' refers to global 'window' object here in a browser
const module = {
  x: 81,
  getX: function() { return this.x; }
};

module.getX();
//  returns 81

const retrieveX = module.getX;
retrieveX();
//  returns 9; the function gets invoked at the global scope

//  Create a new function with 'this' bound to module
//  New programmers might confuse the
//  global variable 'x' with module's property 'x'
const boundGetX = retrieveX.bind(module);
boundGetX();
//  returns 81

Partially applied functions

The next simplest use of bind() is to make a function with pre-specified initial arguments.

These arguments (if any) follow the provided this value and are then inserted at the start of the arguments passed to the target function, followed by whatever arguments are passed bound function at the time it is called.

function list() {
  return Array.prototype.slice.call(arguments);
}

function addArguments(arg1, arg2) {
  return arg1 + arg2
}

const list1 = list(1, 2, 3);
//  [1, 2, 3]

const result1 = addArguments(1, 2);
//  3

// Create a function with a preset leading argument
const leadingThirtysevenList = list.bind(null, 37);

// Create a function with a preset first argument.
const addThirtySeven = addArguments.bind(null, 37);

const list2 = leadingThirtysevenList();
//  [37]

const list3 = leadingThirtysevenList(1, 2, 3);
//  [37, 1, 2, 3]

const result2 = addThirtySeven(5);
//  37 + 5 = 42

const result3 = addThirtySeven(5, 10);
//  37 + 5 = 42
//  (the second argument is ignored)

With setTimeout()

By default within window.setTimeout(), the this keyword will be set to the window (or global) object. When working with class methods that require this to refer to class instances, you may explicitly bind this to the callback function, in order to maintain the instance.

function LateBloomer() {
  this.petalCount = Math.floor(Math.random() * 12) + 1;
}

// Declare bloom after a delay of 1 second
LateBloomer.prototype.bloom = function() {
  window.setTimeout(this.declare.bind(this), 1000);
};

LateBloomer.prototype.declare = function() {
  console.log(`I am a beautiful flower with ${this.petalCount} petals!`);
};

const flower = new LateBloomer();
flower.bloom();
//  after 1 second, calls 'flower.declare()'

Bound functions used as constructors

Warning: This section demonstrates JavaScript capabilities and documents some edge cases of the bind() method.

The methods shown below are not the best way to do things, and probably should not be used in any production environment.

Bound functions are automatically suitable for use with the new operator to construct new instances created by the target function. When a bound function is used to construct a value, the provided this is ignored.

However, provided arguments are still prepended to the constructor call:

function Point(x, y) {
  this.x = x;
  this.y = y;
}

Point.prototype.toString = function() {
  return `${this.x},${this.y}`;
};

const p = new Point(1, 2);
p.toString();
// '1,2'

//  not supported in the polyfill below,

//  works fine with native bind:

const YAxisPoint = Point.bind(null, 0/*x*/);

const emptyObj = {};
const YAxisPoint = Point.bind(emptyObj, 0/*x*/);

const axisPoint = new YAxisPoint(5);
axisPoint.toString();                    // '0,5'

axisPoint instanceof Point;              // true
axisPoint instanceof YAxisPoint;         // true
new YAxisPoint(17, 42) instanceof Point; // true

Note that you need not do anything special to create a bound function for use with new.

The corollary is that you need not do anything special to create a bound function to be called plainly, even if you would rather require the bound function to only be called using new.

//  Example can be run directly in your JavaScript console
//  ...continued from above

//  Can still be called as a normal function
//  (although usually this is undesired)
YAxisPoint(13);

`${emptyObj.x},${emptyObj.y}`;
// >  '0,13'

If you wish to support the use of a bound function only using new, or only by calling it, the target function must enforce that restriction.

Creating shortcuts

bind() is also helpful in cases where you want to create a shortcut to a function which requires a specific this value.

Take Array.prototype.slice(), for example, which you want to use for converting an array-like object to a real array. You could create a shortcut like this:

const slice = Array.prototype.slice;

// ...

slice.apply(arguments);

With bind(), this can be simplified.

In the following piece of code, slice() is a bound function to the apply() function of Function, with the this value set to the slice() function of Array.prototype. This means that additional apply() calls can be eliminated:

//  same as "slice" in the previous example
const unboundSlice = Array.prototype.slice;
const slice = Function.prototype.apply.bind(unboundSlice);

// ...

slice(arguments);

Polyfill

Because older browsers are generally also slower browsers, it is far more critical than most people recognize to create performance polyfills to make the browsing experience in outdated browsers slightly less horrible.

Thus, presented below are two options for Function.prototype.bind() polyfills:

  1. The first one is much smaller and more performant, but does not work when using the new operator.
  2. The second one is bigger and less performant, but it permits some usage of the new operator on bound functions.

Generally, in most code it's very rare to see new used on a bound function, so it is generally best to go with the first option.

//  Does not work with `new (funcA.bind(thisArg, args))`
if (!Function.prototype.bind) (function(){
  var slice = Array.prototype.slice;
  Function.prototype.bind = function() {
    var thatFunc = this, thatArg = arguments[0];
    var args = slice.call(arguments, 1);
    if (typeof thatFunc !== 'function') {
      // closest thing possible to the ECMAScript 5
      // internal IsCallable function
      throw new TypeError('Function.prototype.bind - ' +
             'what is trying to be bound is not callable');
    }
    return function(){
      var funcArgs = args.concat(slice.call(arguments))
      return thatFunc.apply(thatArg, funcArgs);
    };
  };
})();

You can partially work around this by inserting the following code at the beginning of your scripts, allowing use of much of the functionality of bind() in implementations that do not natively support it.

//  Yes, it does work with `new (funcA.bind(thisArg, args))`
if (!Function.prototype.bind) (function(){
  var ArrayPrototypeSlice = Array.prototype.slice;
  Function.prototype.bind = function(otherThis) {
    if (typeof this !== 'function') {
      // closest thing possible to the ECMAScript 5
      // internal IsCallable function
      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
    }

    var baseArgs= ArrayPrototypeSlice.call(arguments, 1),
        baseArgsLength = baseArgs.length,
        fToBind = this,
        fNOP    = function() {},
        fBound  = function() {
          baseArgs.length = baseArgsLength; // reset to default base arguments
          baseArgs.push.apply(baseArgs, arguments);
          return fToBind.apply(
                 fNOP.prototype.isPrototypeOf(this) ? this : otherThis, baseArgs
          );
        };

    if (this.prototype) {
      // Function.prototype doesn't have a prototype property
      fNOP.prototype = this.prototype;
    }
    fBound.prototype = new fNOP();

    return fBound;
  };
})();

Some of the many differences (there may well be others, as this list does not seriously attempt to be exhaustive) between this algorithm and the specified algorithm are:

  • The partial implementation relies on Array.prototype.slice(), Array.prototype.concat(), Function.prototype.call() and Function.prototype.apply(), built-in methods to have their original values.
  • The partial implementation creates functions that do not have immutable "poison pill" caller and arguments properties that throw a TypeError upon get, set, or deletion. (This could be added if the implementation supports Object.defineProperty, or partially implemented [without throw-on-delete behavior] if the implementation supports the __defineGetter__ and __defineSetter__ extensions.)
  • The partial implementation creates functions that have a prototype property. (Proper bound functions have none.)
  • The partial implementation creates bound functions whose length property does not agree with that mandated by ECMA-262: it creates functions with length of 0. A full implementation—depending on the length of the target function and the number of pre-specified arguments—may return a non-zero length.
  • The partial implementation creates bound functions whose name property is not derived from the original function name. According to ECMA-262, name of the returned bound function should be "bound " + name of target function (note the space character).

If you choose to use this partial implementation, you must not rely on those cases where behavior deviates from ECMA-262, 5th edition! Thankfully, these deviations from the specification rarely (if ever) come up in most coding situations. If you do not understand any of the deviations from the specification above, then it is safe in this particular case to not worry about these noncompliant deviation details.

If it's absolutely necessary and performance is not a concern, a far slower (but more specification-compliant solution) can be found at https://github.com/Raynos/function-bind.

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-function.prototype.bind

bind

7

12

4

9

11.6

5.1

4

18

4

12

6

1.0

See also

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

Bitwise AND (&)

The bitwise AND operator (&) returns a 1 in each bit position for which the corresponding bits of both operands are 1s.

Syntax

a & b

Description

The operands are converted to 32-bit integers and expressed by a series of bits (zeroes and ones). Numbers with more than 32 bits get their most significant bits discarded. For example, the following integer with more than 32 bits will be converted to a 32 bit integer:

Before: 11100110111110100000000000000110000000000001
After:              10100000000000000110000000000001

Each bit in the first operand is paired with the corresponding bit in the second operand: first bit to first bit, second bit to second bit, and so on.

The operator is applied to each pair of bits, and the result is constructed bitwise.

The truth table for the AND operation is:

a b a AND b
0 0 0
0 1 0
1 0 0
1 1 1
.    9 (base 10) = 00000000000000000000000000001001 (base 2)
    14 (base 10) = 00000000000000000000000000001110 (base 2)
                   --------------------------------
14 & 9 (base 10) = 00000000000000000000000000001000 (base 2) = 8 (base 10)

Bitwise ANDing any number x with 0 yields 0.

Examples

Using bitwise AND

// 5: 00000000000000000000000000000101
// 2: 00000000000000000000000000000010
5 & 2; // 0

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#prod-BitwiseANDExpression

Bitwise_AND

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/Operators/Bitwise_AND

Bitwise AND assignment (&=)

The bitwise AND assignment operator (&=) uses the binary representation of both operands, does a bitwise AND operation on them and assigns the result to the variable.

Syntax

Operator: x &= y
Meaning:  x  = x & y

Examples

Using bitwise AND assignment

let a = 5;
// 5:     00000000000000000000000000000101
// 2:     00000000000000000000000000000010
a &= 2; // 0

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-assignment-operators

Bitwise_AND_assignment

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/Operators/Bitwise_AND_assignment

Bitwise NOT (~)

The bitwise NOT operator (~) inverts the bits of its operand.

Syntax

~a

Description

The operands are converted to 32-bit integers and expressed by a series of bits (zeroes and ones). Numbers with more than 32 bits get their most significant bits discarded. For example, the following integer with more than 32 bits will be converted to a 32 bit integer:

Before: 11100110111110100000000000000110000000000001
After:              10100000000000000110000000000001

Each bit in the first operand is paired with the corresponding bit in the second operand: first bit to first bit, second bit to second bit, and so on.

The operator is applied to each pair of bits, and the result is constructed bitwise.

The truth table for the NOT operation is:

a NOT a
0 1
1 0
 9 (base 10) = 00000000000000000000000000001001 (base 2)
               --------------------------------
~9 (base 10) = 11111111111111111111111111110110 (base 2) = -10 (base 10)

Bitwise NOTing any number x yields -(x + 1). For example, ~-5 yields 4.

Note that due to using 32-bit representation for numbers both ~-1 and ~4294967295 (232-1) results in 0.

Examples

Using bitwise NOT

~0;  // -1
~-1; // 0
~1;  // -2

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-bitwise-not-operator

Bitwise_NOT

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/Operators/Bitwise_NOT

Bitwise OR (|)

The bitwise OR operator (|) returns a 1 in each bit position for which the corresponding bits of either or both operands are 1s.

Syntax

a | b

Description

The operands are converted to 32-bit integers and expressed by a series of bits (zeroes and ones). Numbers with more than 32 bits get their most significant bits discarded. For example, the following integer with more than 32 bits will be converted to a 32 bit integer:

Before: 11100110111110100000000000000110000000000001
After:              10100000000000000110000000000001

Each bit in the first operand is paired with the corresponding bit in the second operand: first bit to first bit, second bit to second bit, and so on.

The operator is applied to each pair of bits, and the result is constructed bitwise.

The truth table for the OR operation is:

a b a OR b
0 0 0
0 1 1
1 0 1
1 1 1
.    9 (base 10) = 00000000000000000000000000001001 (base 2)
    14 (base 10) = 00000000000000000000000000001110 (base 2)
                   --------------------------------
14 | 9 (base 10) = 00000000000000000000000000001111 (base 2) = 15 (base 10)

Bitwise ORing any number x with 0 yields x.

Examples

Using bitwise OR

// 9  (00000000000000000000000000001001)
// 14 (00000000000000000000000000001110)

14 | 9;
// 15 (00000000000000000000000000001111)

Specifications

Specification
ECMAScript (ECMA-262)

The definition of 'Bitwise OR expression' in that specification.

Bitwise_OR

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/Operators/Bitwise_OR

Bitwise OR assignment (|=)

The bitwise OR assignment operator (|=) uses the binary representation of both operands, does a bitwise OR operation on them and assigns the result to the variable.

Syntax

Operator: x |= y
Meaning:  x = x | y

Examples

Using bitwise OR assignment

let a = 5;
a |= 2; // 7
// 5: 00000000000000000000000000000101
// 2: 00000000000000000000000000000010
// -----------------------------------
// 7: 00000000000000000000000000000111

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-assignment-operators

Bitwise_OR_assignment

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/Operators/Bitwise_OR_assignment

Bitwise XOR (^)

The bitwise XOR operator (^) returns a 1 in each bit position for which the corresponding bits of either but not both operands are 1s.

Syntax

a ^ b

Description

The operands are converted to 32-bit integers and expressed by a series of bits (zeroes and ones). Numbers with more than 32 bits get their most significant bits discarded. For example, the following integer with more than 32 bits will be converted to a 32 bit integer:

Before: 11100110111110100000000000000110000000000001
After:              10100000000000000110000000000001

Each bit in the first operand is paired with the corresponding bit in the second operand: first bit to first bit, second bit to second bit, and so on.

The operator is applied to each pair of bits, and the result is constructed bitwise.

The truth table for the XOR operation is:

a b a XOR b
0 0 0
0 1 1
1 0 1
1 1 0
.    9 (base 10) = 00000000000000000000000000001001 (base 2)
    14 (base 10) = 00000000000000000000000000001110 (base 2)
                   --------------------------------
14 ^ 9 (base 10) = 00000000000000000000000000000111 (base 2) = 7 (base 10)

Bitwise XORing any number x with 0 yields x.

Examples

Using bitwise XOR

// 9  (00000000000000000000000000001001)
// 14 (00000000000000000000000000001110)

14 ^ 9;
// 7  (00000000000000000000000000000111)

Specifications

Specification
ECMAScript (ECMA-262)

The definition of 'Bitwise XOR expression' in that specification.

Bitwise_XOR

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/Operators/Bitwise_XOR

Bitwise XOR assignment (^=)

The bitwise XOR assignment operator (^=) uses the binary representation of both operands, does a bitwise XOR operation on them and assigns the result to the variable.

Syntax

Operator: x ^= y
Meaning:  x  = x ^ y

Examples

Using bitwise XOR assignment

let a = 5;      // 00000000000000000000000000000101
a ^= 3;         // 00000000000000000000000000000011

console.log(a); // 00000000000000000000000000000110
// 6

let b = 5;      // 00000000000000000000000000000101
b ^= 0;         // 00000000000000000000000000000000

console.log(b); // 00000000000000000000000000000101
// 5

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-assignment-operators

Bitwise_XOR_assignment

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/Operators/Bitwise_XOR_assignment

String.prototype.blink()

Deprecated

This feature is no longer recommended. Though some browsers might still support it, it may have already been removed from the relevant web standards, may be in the process of being dropped, or may only be kept for compatibility purposes. Avoid using it, and update existing code if possible; see the compatibility table at the bottom of this page to guide your decision. Be aware that this feature may cease to work at any time.

The blink() method creates a <blink> HTML element that causes a string to blink.

Warning: Blinking text is frowned upon by several accessibility standards. The <blink> element itself is non-standard and deprecated!

Syntax

blink()

Return value

A string containing a <blink> HTML element.

Description

The blink() method embeds a string in a <blink> element: "<blink>str</blink>".

Examples

Using blink()

The following example uses string methods to change the formatting of a string:

var worldString = 'Hello, world';

console.log(worldString.blink());   // <blink>Hello, world</blink>
console.log(worldString.bold());    // <b>Hello, world</b>
console.log(worldString.italics()); // <i>Hello, world</i>
console.log(worldString.strike());  // <strike>Hello, world</strike>

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-string.prototype.blink

blink

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/Global_Objects/String/blink

block

A block statement (or compound statement in other languages) is used to group zero or more statements. The block is delimited by a pair of braces ("curly brackets") and may optionally be labelled:

Syntax

Block Statement

{
  StatementList
}

Labelled Block Statement

LabelIdentifier: {
  StatementList
}

StatementList
Statements grouped within the block statement.

LabelIdentifier
An optional label for visual identification or as a target for break.

Description

The block statement is often called compound statement in other languages. It allows you to use multiple statements where JavaScript expects only one statement. Combining statements into blocks is a common practice in JavaScript. The opposite behavior is possible using an empty statement, where you provide no statement, although one is required.

Blocks are commonly used in association with if...else and for statements.

Examples

Block scoping rules with var or function declaration in non-strict mode

Variables declared with var or created by function declarations in non-strict mode do not have block scope. Variables introduced within a block are scoped to the containing function or script, and the effects of setting them persist beyond the block itself. In other words, block statements do not introduce a scope. For example:

var x = 1;
{
  var x = 2;
}
console.log(x); // logs 2

This logs 2 because the var x statement within the block is in the same scope as the var x statement before the block.

In non-strict code, function declarations inside blocks behave strangely. Do not use them.

Block scoping rules with let, const or function declaration in strict mode

By contrast, identifiers declared with let and const do have block scope:

let x = 1;
{
  let x = 2;
}
console.log(x); // logs 1

The x = 2 is limited in scope to the block in which it was defined.

The same is true of const:

const c = 1;
{
  const c = 2;
}
console.log(c); // logs 1 and does not throw SyntaxError...

Note that the block-scoped const c = 2 does not throw a SyntaxError: Identifier 'c' has already been declared because it can be declared uniquely within the block.

In strict mode, starting with ES2015, functions inside blocks are scoped to that block. Prior to ES2015, block-level functions were forbidden in strict mode.

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-block

block

1

12

1

11

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/block

String.prototype.bold()

Deprecated

This feature is no longer recommended. Though some browsers might still support it, it may have already been removed from the relevant web standards, may be in the process of being dropped, or may only be kept for compatibility purposes. Avoid using it, and update existing code if possible; see the compatibility table at the bottom of this page to guide your decision. Be aware that this feature may cease to work at any time.

The bold() method creates a <b> HTML element that causes a string to be displayed as bold.

Syntax

bold()

Return value

A string containing a <b> HTML element.

Description

The bold() method embeds a string in a <b> element: "<b>str</b>".

Examples

Using bold()

The following example uses string methods to change the formatting of a string:

var worldString = 'Hello, world';

console.log(worldString.blink());   // <blink>Hello, world</blink>
console.log(worldString.bold());    // <b>Hello, world</b>
console.log(worldString.italics()); // <i>Hello, world</i>
console.log(worldString.strike());  // <strike>Hello, world</strike>

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-string.prototype.bold

bold

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/Global_Objects/String/bold

Boolean

The Boolean object is an object wrapper for a boolean value.

Description

The value passed as the first parameter is converted to a boolean value, if necessary. If the value is omitted or is 0, -0, null, false, NaN, undefined, or the empty string (""), the object has an initial value of false. All other values, including any object, an empty array ([]), or the string "false", create an object with an initial value of true.

Do not confuse the primitive Boolean values true and false with the true and false values of the Boolean object.

Any object of which the value is not undefined or null, including a Boolean object whose value is false, evaluates to true when passed to a conditional statement. For example, the condition in the following if statement evaluates to true:

var x = new Boolean(false);
if (x) {
  // this code is executed
}

This behavior does not apply to Boolean primitives. For example, the condition in the following if statement evaluates to false:

var x = false;
if (x) {
  // this code is not executed
}

Do not use a Boolean object to convert a non-boolean value to a boolean value. To perform this task, instead, use Boolean as a function, or a double NOT operator:

var x = Boolean(expression);     // use this...
var x = !!(expression);          // ...or this
var x = new Boolean(expression); // don't use this!

If you specify any object, including a Boolean object whose value is false, as the initial value of a Boolean object, the new Boolean object has a value of true.

var myFalse = new Boolean(false);   // initial value of false
var g = Boolean(myFalse);       // initial value of true
var myString = new String('Hello'); // string object
var s = Boolean(myString);      // initial value of true

Do not use a Boolean object in place of a Boolean primitive.

Note: When the non-standard property document.all is used as an argument for this constructor, the result is a Boolean object with the value false. This property is legacy and non-standard and should not be used.

Constructor

Boolean()
Creates a new Boolean object.

Instance methods

Boolean.prototype.toString()
Returns a string of either true or false depending upon the value of the object. Overrides the Object.prototype.toString() method.

Boolean.prototype.valueOf()
Returns the primitive value of the Boolean object. Overrides the Object.prototype.valueOf() method.

Examples

Creating Boolean objects with an initial value of false

var bNoParam = new Boolean();
var bZero = new Boolean(0);
var bNull = new Boolean(null);
var bEmptyString = new Boolean('');
var bfalse = new Boolean(false);

Creating Boolean objects with an initial value of true

var btrue = new Boolean(true);
var btrueString = new Boolean('true');
var bfalseString = new Boolean('false');
var bSuLin = new Boolean('Su Lin');
var bArrayProto = new Boolean([]);
var bObjProto = new Boolean({});

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-boolean-objects

Boolean

1

12

1

3

3

1

1

18

4

10.1

1

1.0

Boolean

1

12

1

3

4

1

1

18

4

10.1

1

1.0

toSource

No

No

1-74

Starting in Firefox 74, toSource() is no longer available for use by web content. It is still allowed for internal and privileged code.

No

No

No

No

No

4

No

No

No

toString

1

12

1

3

4

1

1

18

4

10.1

1

1.0

valueOf

1

12

1

4

4

1

1

18

4

10.1

1

1.0

See also

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

break

The break terminates the current loop, switch, or label statement and transfers program control to the statement following the terminated statement.

Syntax

break [label];

label Optional
Identifier associated with the label of the statement. If the statement is not a loop or switch, this is required.

Description

The break statement includes an optional label that allows the program to break out of a labeled statement. The break statement needs to be nested within the referenced label. The labeled statement can be any block statement; it does not have to be preceded by a loop statement.

A break statement, with or without a following label, cannot be used within the body of a function that is itself nested within the current loop, switch, or label statement that the break statement is intended to break out of.

Examples

break in while loop

The following function has a break statement that terminates the while loop when i is 3, and then returns the value 3 * x.

function testBreak(x) {
  var i = 0;

  while (i < 6) {
    if (i == 3) {
      break;
    }
    i += 1;
  }

  return i * x;
}

break in switch statements

The following code has a break statement that terminates the switch statement when a case is matched and the corresponding code has ran

const food = "sushi";

switch (food) {
  case "sushi":
    console.log("Sushi is originally from Japan.");
    break;
  case "pizza":
    console.log("Pizza is originally from Italy.");
    break;
  default:
    console.log("I have never heard of that dish.");
    break;
}

break in labeled blocks

The following code uses break statements with labeled blocks. A break statement must be nested within any label it references. Notice that inner_block is nested within outer_block.

outer_block: {
  inner_block: {
    console.log('1');
    break outer_block; // breaks out of both inner_block and outer_block
    console.log(':-('); // skipped
  }
  console.log('2'); // skipped
}

break in labeled blocks that throw

The following code also uses break statements with labeled blocks, but generates a SyntaxError because its break statement is within block_1 but references block_2. A break statement must always be nested within any label it references.

block_1: {
  console.log('1');
  break block_2; // SyntaxError: label not found
}

block_2: {
  console.log('2');
}

break within functions

SyntaxErrors are also generated in the following code examples which use break statements within functions that are nested within a loop, or labeled block that the break statements are intended to break out of.

function testBreak(x) {
  var i = 0;

  while (i < 6) {
    if (i == 3) {
      (function() {
        break;
      })();
    }
    i += 1;
  }

return i * x;
}

testBreak(1); // SyntaxError: Illegal break statement

block_1: {
  console.log('1');
  ( function() {
    break block_1; // SyntaxError: Undefined label 'block_1'
  })();
}

Specifications

Specification
ECMAScript (ECMA-262)

The definition of 'Break statement' in that specification.

break

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/break

WebAssembly.Memory.prototype.buffer

The buffer prototype property of the WebAssembly.Memory object returns the buffer contained in the memory.

Examples

Using buffer

The following example (see memory.html on GitHub, and view it live also) fetches and instantiates the loaded memory.wasm byte code using the WebAssembly.instantiateStreaming() method, while importing the memory created in the line above. It then stores some values in that memory, then exports a function and uses it to sum some values.

WebAssembly.instantiateStreaming(fetch('memory.wasm'), { js: { mem: memory } })
.then(obj => {
  var i32 = new Uint32Array(memory.buffer);
  for (var i = 0; i < 10; i++) {
    i32[i] = i;
  }
  var sum = obj.instance.exports.accumulate(0, 10);
  console.log(sum);
});

Specifications

Specification
WebAssembly JavaScript Interface (WebAssembly JavaScript Interface)

#dom-memory-buffer

buffer

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

© 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/Global_Objects/WebAssembly/Memory/buffer

SharedArrayBuffer.prototype.byteLength

The byteLength accessor property represents the length of an SharedArrayBuffer in bytes.

Description

The byteLength property is an accessor property whose set accessor function is undefined, meaning that you can only read this property. The value is established when the shared array is constructed and cannot be changed.

Examples

Using byteLength

var sab = new SharedArrayBuffer(1024);
sab.byteLength; // 1024

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-get-sharedarraybuffer.prototype.bytelength

byteLength

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).

79

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

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.

89

SharedArrayBuffer is gated behind COOP/COEP. For more detail, read Making your website "cross-origin isolated" using COOP and COEP.

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.

79

57

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

55-57

46-55

No

10.3-11

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

© 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/Global_Objects/SharedArrayBuffer/byteLength

TypedArray.prototype.byteOffset

The byteOffset accessor property represents the offset (in bytes) of a typed array from the start of its ArrayBuffer.

Description

The byteOffset property is an accessor property whose set accessor function is undefined, meaning that you can only read this property. The value is established when a TypedArray is constructed and cannot be changed. TypedArray is one of the TypedArray objects.

Examples

Using the byteOffset property

var buffer = new ArrayBuffer(8);

var uint8 = new Uint8Array(buffer);
uint8.byteOffset; // 0 (no offset specified)

var uint8 = new Uint8Array(buffer, 3);
uint8.byteOffset; // 3 (as specified when constructing Uint8Array)

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-get-%typedarray%.prototype.byteoffset

byteOffset

7

14

4

10

11.6

5.1

4

18

4

12

4.2

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/Global_Objects/TypedArray/byteOffset

TypedArray.BYTES_PER_ELEMENT

The TypedArray.BYTES_PER_ELEMENT property represents the size in bytes of each element in an typed array.

Property attributes of TypedArray.BYTES_PER_ELEMENT

Writable

no

Enumerable

no

Configurable

no

Description

TypedArray objects differ from each other in the number of bytes per element and in the way the bytes are interpreted. The BYTES_PER_ELEMENT constant contains the number of bytes each element in the given TypedArray has.

Examples

Using BYTES_PER_ELEMENT

Int8Array.BYTES_PER_ELEMENT;         // 1
Uint8Array.BYTES_PER_ELEMENT;        // 1
Uint8ClampedArray.BYTES_PER_ELEMENT; // 1
Int16Array.BYTES_PER_ELEMENT;        // 2
Uint16Array.BYTES_PER_ELEMENT;       // 2
Int32Array.BYTES_PER_ELEMENT;        // 4
Uint32Array.BYTES_PER_ELEMENT;       // 4
Float32Array.BYTES_PER_ELEMENT;      // 4
Float64Array.BYTES_PER_ELEMENT;      // 8

Specifications

Specification
ECMAScript Language Specification (ECMAScript)

#sec-typedarray.bytes_per_element

BYTES_PER_ELEMENT

7

12

4

10

11.6

5.1

4

18

4

12

4.2

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/Global_Objects/TypedArray/BYTES_PER_ELEMENT

Intl.Locale.prototype.calendar

The Intl.Locale.prototype.calendar property is an accessor property which returns the type of calendar used in the Locale.

Description

The calendar property returns the part of the Locale that indicates the Locale's calendar era. While most of the world uses the Gregorian calendar, there are several regional calendar eras used around the world. The following table shows all the valid Unicode calendar key strings, along with a description of the calendar era they represent.

Unicode calendar keys

Unicode calendar keys
Calendar key (name) Description
buddhist Thai Buddhist calendar
chinese Traditional Chinese calendar
coptic Coptic calendar
dangi Traditional Korean calendar
ethioaa Ethiopic calendar, Amete Alem (epoch approx. 5493 B.C.E)
ethiopic Ethiopic calendar, Amete Mihret (epoch approx, 8 C.E.)
gregory Gregorian calendar
hebrew Traditional Hebrew calendar
indian Indian calendar
islamic Islamic calendar
islamic-umalqura Islamic calendar, Umm al-Qura
islamic-tbla Islamic calendar, tabular (intercalary years [2,5,7,10,13,16,18,21,24,26,29] - astronomical epoch)
islamic-civil Islamic calendar, tabular (intercalary years [2,5,7,10,13,16,18,21,24,26,29] - civil epoch)
islamic-rgsa Islamic calendar, Saudi Arabia sighting
iso8601 ISO calendar (Gregorian calendar using the ISO 8601 calendar week rules)
japanese Japanese Imperial calendar
persian Persian calendar
roc Republic of China calendar

Warning: The islamicc calendar key has been deprecated. Please use islamic-civil.

islamicc

Civil (algorithmic) Arabic calendar

Examples

Adding a calendar in the Locale string

Calendar eras fall under the category of locale key "extension keys". These keys add additional data about the locale, and are added to locale identifiers by using the -u extension. Thus, the calendar era type can be added to the initial locale identifier string that is passed into the Intl.Locale constructor. To add the calendar type, first add the -u extension to the string. Next, add the -ca extension to indicate that you are adding a calendar type. Finally, add the calendar era to the string.

let frBuddhist = new Intl.Locale("fr-FR-u-ca-buddhist");
console.log(frBuddhist.calendar); // Prints "buddhist"

Adding a calendar with a configuration object

The Intl.Locale constructor has an optional configuration object argument, which can contain any of several extension types, including calendars. Set the calendar property of the configuration object to your desired calendar era, and then pass it into the constructor.

let frBuddhist = new Intl.Locale("fr-FR", {calendar: "buddhist"});
console.log(frBuddhist.calendar); // Prints "buddhist"

Specifications

Specification
ECMAScript Internationalization API Specification (ECMAScript Internationalization API)

#sec-Intl.Locale.prototype.calendar

calendar

74

79

75

No

62

14

74

74

79

53

14

11.0

See also

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/calendar

Function.prototype.call()

The call() method calls a function with a given this value and arguments provided individually.

Syntax

call()
call(thisArg)
call(thisArg, arg1)
call(thisArg, arg1, arg2)
call(thisArg, arg1, ... , argN)

Parameters

thisArg Optional
The value to use as this when calling func.

Note: In certain cases, thisArg may not be the actual value seen by the method.

If the method is a function in non-strict mode, null and undefined will be replaced with the global object, and primitive values will be converted to objects.

arg1, arg2, ...argN Optional
Arguments for the function.

Return value

The result of calling the function with the specified this value and arguments.

Description

The call() allows for a function/method belonging to one object to be assigned and called for a different object.

call() provides a new value of this to the function/method. With call(), you can write a method once and then inherit it in another object, without having to rewrite the method for the new object.

Note: While the syntax of this function is almost identical to that of apply(), the fundamental difference is that call() accepts an argument list, while apply() accepts a single array of arguments.

Examples

Using call to chain constructors for an object

You can use call to chain constructors for an object (similar to Java).

In the following example, the constructor for the Product object is defined with two parameters: name and price.

Two other functions, Food and Toy, invoke Product, passing this, name, and price. Product initializes the properties name and price, both specialized functions define the category.

function Product(name, price) {
  this.name = name;
  this.price = price;
}

function Food(name, price) {
  Product.call(this, name, price);
  this.category = 'food';
}

function Toy(name, price) {
  Product.call(this, name, price);
  this.category = 'toy';
}

const cheese = new Food('feta', 5);
const fun = new Toy('robot', 40);

Using call to invoke an anonymous function

In this example, we create an anonymous function and use call to invoke it on every object in an array.

The main purpose of the anonymous function here is to add a print function to every object, which is able to print the correct index of the object in the array.

Note: Passing the object as this value is not strictly necessary, but is done for explanatory purpose.

const animals = [
  { species: 'Lion', name: 'King' },
  { species: 'Whale', name: 'Fail' }
];

for (let i = 0; i < animals.length; i++) {
  (function(i) {
    this.print = function() {
      console.log('#' + i + ' ' + this.species
                  + ': ' + this.name);
    }
    this.print();
  }).call(animals[i], i);
}

Using call to invoke a function and specifying the context for 'this'

In the example below, when we call greet, the value of this will be bound to object obj.

function greet() {
  const reply = [this.animal, 'typically sleep between', this.sleepDuration].join(' ');
  console.log(reply);
}

const obj = {
  animal: 'cats', sleepDuration: '12 and 16 hours'
};

greet.call(obj);  // cats typically sleep between 12 and 16 hours

Using call to invoke a function and without specifying the first argument

In the example below, we invoke the display function without passing the first argument. If the first argument is not passed, the value of this is bound to the global object.

var sData = 'Wisen';

function display() {
  console.log('sData value is %s ', this.sData);
}

display.call();  // sData value is Wisen

Note: In strict mode, the value of this will be undefined. See below.

'use strict';

var sData = 'Wisen';

function display() {
  console.log('sData value is %s ', this.sData);
}

display.call(); // Cannot read the property of 'sData' of undefined

Specifications

Specification
ECMAScript (ECMA-262)

The definition of 'Function.prototype.call' in that specification.

call

1

12

1

5.5

4

1

1

18

4

10.1

1

1.0

See also

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

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: 'this' is not a Set object (EdgE)
TypeError: Function.prototype.toString called on incompatible object (Firefox)
TypeError: Function.prototype.bind called on incompatible target (Firefox)
TypeError: Method Set.prototype.add called on incompatible receiver undefined (Chrome)
TypeError: Bind must be called on a function (Chrome)

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 provide a lambda which is making the call, or use the Function.prototype.bind() function to force the this argument to the expected object.

Examples

Invalid cases

var mySet = new Set;
['bar', 'baz'].forEach(mySet.add);
// mySet.add is a function, but "mySet" is not captured as this.

var myFun = function () {
  console.log(this);
};
['bar', 'baz'].forEach(myFun.bind);
// myFun.bind is a function, but "myFun" is not captured as this.

Valid cases

var mySet = new Set;
['bar', 'baz'].forEach(mySet.add.bind(mySet));
// This works due to binding "mySet" as this.

var myFun = function () {
  console.log(this);
};
['bar', 'baz'].forEach(x => myFun.bind(x));
// This works using the "bind" function. It creates a lambda forwarding the argument.

See also

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

arguments.callee

The arguments.callee property contains the currently executing function.

Description

callee is a property of the arguments object. It can be used to refer to the currently executing function inside the function body of that function. This is useful when the name of the function is unknown, such as within a function expression with no name (also called "anonymous functions").

Warning: The 5th edition of ECMAScript (ES5) forbids use of arguments.callee() in strict mode. Avoid using arguments.callee() by either giving function expressions a name or use a function declaration where a function must call itself.

Why was arguments.callee removed from ES5 strict mode?

(adapted from a Stack Overflow answer by olliej)

Early versions of JavaScript did not allow named function expressions, and for this reason you could not make a recursive function expression.

For example, this syntax worked:

function factorial (n) {
    return !(n > 1) ? 1 : factorial(n - 1) * n;
}

[1, 2, 3, 4, 5].map(factorial);

but:

[1, 2, 3, 4, 5].map(function(n) {
    return !(n > 1) ? 1 : /* what goes here? */ (n - 1) * n;
});

did not. To get around this arguments.callee was added so you could do

[1, 2, 3, 4, 5].map(function(n) {
    return !(n > 1) ? 1 : arguments.callee(n - 1) * n;
});

However, this was actually a really bad solution as this (in conjunction with other arguments, callee, and caller issues) make inlining and tail recursion impossible in the general case (you can achieve it in select cases through tracing, etc., but even the best code is suboptimal due to checks that would not otherwise be necessary.) The other major issue is that the recursive call will get a different this value, e.g.:

var global = this;

var sillyFunction = function(recursed) {
    if (!recursed) { return arguments.callee(true); }
    if (this !== global) {
        alert('This is: ' + this);
    } else {
        alert('This is the global');
    }
}

sillyFunction();

ECMAScript 3 resolved these issues by allowing named function expressions. For example:

[1, 2, 3, 4, 5].map(function factorial(n) {
    return !(n > 1) ? 1 : factorial(n - 1)*n;
});

This has numerous benefits:

  • the function can be called like any other from inside your code
  • it does not create a variable in the outer scope (except for IE 8 and below)
  • it has better performance than accessing the arguments object

Another feature that was deprecated was arguments.callee.caller, or more specifically Function.caller. Why is this? Well, at any point in time you can find the deepest caller of any function on the stack, and as I said above looking at the call stack has one single major effect: it makes a large number of optimizations impossible, or much more difficult. For example, if you cannot guarantee that a function f will not call an unknown function, it is not possible to inline f. Basically it means that any call site that may have been trivially inlinable accumulates a large number of guards:

function f(a, b, c, d, e) { return a ? b * c : d * e; }

If the JavaScript interpreter cannot guarantee that all the provided arguments are numbers at the point that the call is made, it needs to either insert checks for all the arguments before the inlined code, or it cannot inline the function. Now in this particular case a smart interpreter should be able to rearrange the checks to be more optimal and not check any values that would not be used. However in many cases that's just not possible and therefore it becomes impossible to inline.

Examples

Using arguments.callee in an anonymous recursive function

A recursive function must be able to refer to itself. Typically, a function refers to itself by its name. However, an anonymous function (which can be created by a function expression or the Function constructor) does not have a name. Therefore if there is no accessible variable referring to it, the only way the function can refer to itself is by arguments.callee.

The following example defines a function, which, in turn, defines and returns a factorial function. This example isn't very practical, and there are nearly no cases where the same result cannot be achieved with named function expressions.

function create() {
   return function(n) {
      if (n <= 1)
         return 1;
      return n * arguments
⚠️ **GitHub.com Fallback** ⚠️