demo2s-1

Must Watch!



MustWatch



Implementations

JavaScript is a scripting language designed to interact with web pages and is made up of the following three distinct parts: The Core (ECMAScript) The Document Object Model (DOM) The Browser Object Model (BOM) JavaScript and ECMAScript are often used synonymously, but JavaScript is much more than just what is defined in ECMA-262.

ECMAScript

ECMAScript, the language defined in ECMA-262, isn't tied to web browsers. ECMA-262 defines this language as a base upon which more-robust scripting languages may be built. Web browsers are just one host environment in which an ECMAScript implementation may exist. Extensions, such as the Document Object Model (DOM), use ECMAScript's core types and syntax to provide additional functionality that's more specific to the environment. Other host environments include NodeJS, a server-side JavaScript platform, and the increasingly obsolete Adobe Flash. ECMA-262 describes the following parts of the language: Syntax Types Statements Keywords Reserved words Operators Global objects ECMAScript is a description of a language implementing all of the facets described in the specification. JavaScript implements ECMAScript, but so does Adobe ActionScript. The different versions of ECMAScript are defined as editions. For example, the ECMA-262 edition 7 is released in 2016.

The Document Object Model

The Document Object Model (DOM) is an application programming interface (API) for XML that was extended for use in HTML. The DOM maps out an entire page as a hierarchy of nodes. Each part of an HTML or XML page is a type of node. By creating a tree to represent a document, the DOM can control its content and structure. Nodes can be removed, added, replaced, and modified by using the DOM API.

The Browser Object Model

The BOM deals with the browser window and frames. For example, with BOM we can pop up new browser windows, move, resize, and close browser windows

<script> Element, attribute and its meaning

The primary method of inserting JavaScript into an HTML page is via the <script> element. There are six attributes for the <script> element:
Attribute Optional Description
async Optional The script should begin downloading immediately.
Should not prevent other actions on the page such as downloading resources or waiting for other scripts to load.
Valid only for external script files.
charset Optional The character set of the code specified using the src attribute.
This attribute is rarely used.
crossorigin Optional Configures the settings for the associated request.
crossorigin="anonymous" will configure the request for the file to not have the credentials flag set.
crossorigin="use-credentials" will set the credentials flag, meaning the outgoing request will include credentials.
defer Optional Indicates that the execution of the script can safely be deferred until after the document's content has been completely parsed and displayed.
Valid only for external scripts.
integrity Optional Allows for verification of Sub resource Integrity (SRI) by checking the retrieved resource against a provided cryptographic signature.
If the signature of the retrieved resource does not match that specified by this attribute, the page will error and the script will not execute.
language Deprecated Originally indicated the scripting language being used by the code block
src Optional Indicates an external file that contains code to be executed.
type Optional Replaces language attribute.
indicates the content type, also called MIME type of the scripting language.
If the value is module, the code is treated as an ES6 module and only then is eligible to use the import and export keywords.

<script> Usage

There are two ways to use the <script> element: embed JavaScript code directly into the page or include JavaScript from an external file. To include inline JavaScript code, place JavaScript code inside the <script> element directly, as follows: function test() { console.log("Hi!"); } </script> The JavaScript code contained inside a <script> element is interpreted from top to bottom. In the case of this example, a function definition is interpreted and stored inside the interpreter environment. The rest of the page content is not loaded and/or displayed until after all of the code inside the <script> element has been evaluated. When using inline JavaScript code, you cannot have the string "</script>" anywhere in your code. For example, the following code causes an error when loaded into a browser: <script> function test() { console.log("</script>"); } </script> You can escape the "/" character, as follows: <script> function test() { console.log("<\/script>"); } </script> To include JavaScript from an external file, the src attribute is required. The value of src is a URL linked to a file containing JavaScript code, like this: <script src="example.js"></script> In this example, an external file named example.js is loaded into the page. The file need only contain the JavaScript code that would occur between the opening <script> and closing </script> tags. Processing of the page is halted while the external file is interpreted. In XHTML documents, you can omit the closing tag, as in this example: <script src="example.js"/> By convention, external JavaScript files have a .js extension. If you don't use a .js extension, double-check that your server is returning the correct MIME type. The <script> elements are interpreted in the order in which they appear in the page so long as the defer and async attributes are not present.

<script> Tag Placement

Traditionally, all <script> elements were placed within the <head> element on a page, as in this example: <!DOCTYPE html> <html> <head> <title>Example HTML Page</title> <script src="example1.js"></script> <script src="example2.js"></script> </head> <body> <!-- content here --> </body> </html> Including all JavaScript files in the <head> of a document means that all of the JavaScript code must be downloaded, parsed, and interpreted before the page begins rendering. The rendering begins when the browser receives the opening <body> tag. This may cause a noticeable delay in page rendering. For this reason, modern web applications typically include all JavaScript references in the <body> element, after the page content, as shown in this example: <!DOCTYPE html> <html> <head> <title>Example HTML Page</title> </head> <body> <!-- content here --> <!-- content here --> <!-- content here --> <script src="example1.js"></script> <script src="example2.js"></script> </body> </html> Using this approach, the page is completely rendered in the browser before the JavaScript code is processed.

<script> deferred Scripts

HTML 4.01 defines an attribute named defer for the <script> element. defer indicates that a script won't be changing the structure of the page as it executes. The script can be run safely after the entire page has been parsed. Setting the defer attribute on a <script> element signals to the browser that download should begin immediately but execution should be deferred: <!DOCTYPE html> <html> <head> <title>Example HTML Page</title> <script defer src="example1.js"></script> <script defer src="example2.js"></script> </head> <body> <!-- content here --> </body> </html>

Note

Even though the two <script> elements are included in the document <head>, they will not be executed until after the browser has received the closing </html> tag. The defer attribute is supported only for external script files. Some browsers may ignore this attribute. We should put deferred scripts at the bottom of the page. For XHTML documents, specify the defer attribute as defer="defer".

Asynchronous Scripts

HTML5 adds the async attribute for <script> elements. The async attribute changes the way the script is processed. async applies only to external scripts and signals the browser to begin downloading the file immediately. Unlike defer, scripts marked as async are not guaranteed to execute in the order in which they are specified. For example: <!DOCTYPE html> <html> <head> <title>Example HTML Page</title> <script async src="example1.js"></script> <script async src="example2.js"></script> </head> <body> <!-- content here --> </body> </html> In this code, the second script file might execute before the first. There should be no dependencies between the two script files. For XHTML documents, specify the async attribute as async="async".

<noscript> element

The <noscript> element was created to provide alternate content for browsers without JavaScript. This element is useful for browsers that explicitly disable JavaScript. The <noscript> element can contain any HTML elements, aside from <script>, that can be included in the document <body>. Any content contained in a <noscript> element will be displayed under only the following two circumstances: The browser doesn't support scripting. The browser's scripting support is turned off. If either of these conditions is met, then the content inside the <noscript> element is rendered. In all other cases, the browser does not render the content of <noscript>. Here is a simple example: <!DOCTYPE html> <html> <head> <title>Example HTML Page</title> <script src="example1.js"></script> <script src="example2.js"></script> </head> <body> <noscript> <p>This page requires a JavaScript-enabled browser.</p> </noscript> </body> </html> In this example, a message is displayed to the user when the scripting is not available. For scripting-enabled browsers, this message will never be seen even though it is still a part of the page.

Case-Sensitivity

ECMAScript's syntax borrows heavily from C and other C-like languages such as Java and Perl. Javascript is case-sensitive. The variables, function names, and operators are all case-sensitive. JavaScript language keywords, variables, function names, and other identifiers must always be typed with a consistent capitalization of letters. The while keyword, for example, must be typed "while," not "While" or "WHILE." A variable named test is different from a variable named Test. let test = 'a'; let Test = 'v'; console.log(test); console.log(Test); Output:

Identifiers

An identifier is the name of a variable, function, property, or function argument. Identifiers may be one or more characters in the following format: The first character must be a letter, an underscore _, or a dollar sign $. All other characters may be letters, underscores, dollar signs, or numbers. Letters in an identifier may include extended ASCII or Unicode letter characters. JavaScript identifiers are used to name constants, variables, properties, functions, and classes and to provide labels for certain loops in JavaScript code. A JavaScript identifier must begin with a letter, an underscore (_), or a dollar sign ($). Subsequent characters can be letters, digits, underscores, or dollar signs. Digits are not allowed as the first character. By convention, ECMAScript identifiers use camel case, meaning that the first letter is lowercase and each additional word is offset by a capital letter, like this: firstSecondThird myCarIsGood doSomethingImportantAnd These are all legal identifiers: x my_variable_name v13 _dummy $string $$abc Keywords, reserved words, true, false, and null cannot be used as identifiers. let firstSecondThird = 'a'; console.log(firstSecondThird); Output:

Comments

ECMAScript uses C-style comments for both single-line and block comments. A single-line comment begins with two forward-slash characters, such as this: // single line comment A block comment begins with a forward slash and asterisk (/*) and ends with the opposite (*/), as in this example: /* This is a multi-line comment */

Example

The following code adds some comments to a simple script. //This is a test file let a= 'a'; /* The following code output message to console */ console.log(a); Output:

Strict Mode

ECMAScript strict mode is a different parsing and execution model for JavaScript. To enable strict mode for an entire script, include the following at the top: "use strict"; This is a pragma that tells supporting JavaScript engines to change into strict mode. You may also specify just a function to execute in strict mode by including the pragma at the top of the function body: function doSomething() { "use strict"; // function body } Strict mode changes how JavaScript is executed. All modern browsers support strict mode. "use strict" does not include any language keywords: the directive is just an expression statement that consists of a special string literal (in single or double quotes). "use strict" can appear only at the start of a script or at the start of a function body, before any real statements have appeared.

Statements

Statements in ECMAScript are terminated by a semicolon. Omitting the semicolon makes the parser determine where the end of a statement occurs. let sum = a + b // valid even without a semicolon - not recommended let diff = a - b; // valid - preferred Even though a semicolon is not required at the end of statements, you should always include one. Including semicolons helps prevent errors of omission. Including semicolons also improves performance in certain situations. Multiple statements can be combined into a code block by using C-style syntax, beginning with a left curly brace { and ending with a right curly brace }: let test = true; if (test) { test = false; console.log(test); } Control statements, such as if, require code blocks only when executing multiple statements. It is a best practice to always use code blocks with control statements, even if there's only one statement to be executed: let test = true; // valid, but error-prone and should be avoided if (test) console.log(test); // preferred if (test) { console.log(test); } Using code blocks for control statements makes the intent clearer, and there's less chance for errors when changes need to be made.

Keywords And Reserved Words

ECMA-262 describes a set of reserved keywords that have specific uses. The keywords are reserved and cannot be used as identifiers or property names. The complete list of keywords for ECMA-262, sixth edition is as follows: break do in typeof case else instanceof var catch export new void class extends return while const finally super with continue for switch yield debugger function this default if throw delete import try The specification also describes a set of future reserved words that cannot be used as identifiers or property names. Though reserved words don't have any specific usage in the language, they are reserved for future use as keywords. The following is the complete list of future reserved words defined in ECMA-262, sixth edition: Always reserved: enum Reserved in strict mode: implements package public interface protected static let private Reserved in module code: await These words may still not be used as identifiers but now can be used as property names in objects. We should avoid using both keywords and reserved words as both identifiers and property names to ensure compatibility with past and future ECMAScript editions.

Try Out

With Browser Developer Tools

We try out short JavaScript code in a browser with the following steps: Open up the web developer tools in your web browser (with F12, Ctrl-Shift-I, or Command-Option-I) and Select the Console tab. Type code at the prompt See the results as you type. Browser developer tools often appear as panes at the bottom or right of the browser window, but you can usually detach them as separate windows, which is often quite convenient.

Node.js

Another way to try out JavaScript code is to download and install Node from https://nodejs.org. Once Node is installed on your system, you can simply open a Terminal window and type node to begin an interactive JavaScript session like this one: $ node/*w w w .d e mo 2 s . co m */ Welcome to Node.js v15.2.1. Type ".help" for more information. > .help .break Sometimes you get stuck, this gets you out .clear Alias for .break .editor Enter editor mode .exit Exit the REPL .help Print this help message .load Load JS from a file into the REPL session .save Save all evaluated commands in this REPL session to a file Press Ctrl+C to abort current expression, Ctrl+D to exit the REPL > > let x = 2, y = 3; undefined > x + y 5 > (x === 2) && (y === 3) true > (x > 3) || (y < 3) false

Hello World

You can write your code in a text editor. From there, you can copy and paste to the JavaScript console or into a Node session. Or you can save your code to a file with file name extension .js and then run that file of JavaScript code with Node: $ node yourFileName.js If you use Node in a non interactive manner like this, it won't automatically print out the value of all the code you run. You can use the function console.log() to display text and other JavaScript values in your terminal window or in a browser's developer tools console. So, for example, if you create a hello.js file containing this line of code: console.log("Hello World!"); and execute the file with node hello.js, you'll see the message "Hello World!" printed out. If you want to see that same message printed out in the JavaScript console of a web browser, create a new file named hello.html, and put this text in it: <script src="hello.js"></script> Then load hello.html into your web browser using a file:// URL like this one: file:///Users/username/javascript/hello.html Open the developer tools window to see the greeting in the console. You can drag and drop your html file to browser.

Quick Syntax Reference

This section presents a quick introduction, through code examples, to the JavaScript language. Anything following double slashes is an English-language comment. They explain the JavaScript code.

Variable

A variable is a symbolic name for a value. Variables are declared with the let keyword: let x; // Declare a variable named x. Values can be assigned to variables with an = sign x = 0; // Now the variable x has the value 0 x // => 0: A variable evaluates to its value.

Data Types

JavaScript supports several types of values x = 1; // Numbers. x = 0.01; // Numbers can be integers or reals. x = "hello world"; // Strings of text in quotation marks. x = 'JavaScript'; // Single quote marks also delimit strings. x = true; // A Boolean value. x = false; // The other Boolean value. x = null; // Null is a special value that means "no value." x = undefined; // Undefined is another special value like null.

Object

JavaScript also have objects and arrays. JavaScript's most important datatype is the object. An object is a collection of name/value pairs, or a string to value map. let book = { // Objects are enclosed in curly braces. topic: "JavaScript", // The property "topic" has value "JavaScript." edition: 7 // The property "edition" has value 7 }; // The curly brace marks the end of the object. Access the properties of an object with . or []: book.topic // => "JavaScript" book["edition"] // => 7: another way to access property values. book.author = "CSS"; // Create new properties by assignment. book.contents = {}; // {} is an empty object with no properties. book.contents?.c?.s // => undefined: book.contents has no c property. JavaScript also supports arrays of values: let myArray = [2, 3, 5, 7]; // An array of 4 values, delimited with [ and ]. myArray[0] // => 2: the first element (index 0) of the array. myArray.length // => 4: how many elements in the array. myArray[myArray.length-1] // => 7: the last element of the array. myArray[4] = 9; // Add a new element by assignment. myArray[4] = 11; // Or alter an existing element by assignment. let empty = []; // [] is an empty array with no elements. empty.length // => 0 Arrays and objects can hold other arrays and objects: let points = [ // An array with 2 elements. {x: 0, y: 0}, // Each element is an object. {x: 1, y: 1} ]; let data = { // An object with 2 properties trial1: [[1,2], [3,4]], // The value of each property is an array. trial2: [[2,3], [4,5]] // The elements of the arrays are arrays. };

Operators

To form expressions in JavaScript, use operators: Operators act on values to produce a new value. Arithmetic operators are simple: 3 + 2 // => 5: addition 3 - 2 // => 1: subtraction 3 * 2 // => 6: multiplication 3 / 2 // => 1.5: division "3" + "2" // => "32": + adds numbers and concatenates strings JavaScript defines some shorthand arithmetic operators let count = 0; // Define a variable count++; // Increment the variable count--; // Decrement the variable count += 2; // Add 2: same as count = count + 2; count *= 3; // Multiply by 3: same as count = count * 3; count // => 6: variable names are expressions, too. Equality and relational operators test whether two values are equal, unequal, less than, greater than, and so on. They evaluate to true or false. let x = 2, y = 3; // These = signs are assignment, not equality tests x === y // => false: equality x !== y // => true: inequality x < y // => true: less-than x <= y // => true: less-than or equal x > y // => false: greater-than x >= y // => false: greater-than or equal "two" === "three" // => false: the two strings are different "two" > "three" // => true: "tw" is alphabetically greater than "th" false === (x > y) // => true: false is equal to false Logical operators combine or invert boolean values (x === 2) && (y === 3) // => true: both comparisons are true. && is AND (x > 3) || (y < 3) // => false: neither comparison is true. || is OR !(x === y) // => true: ! inverts a boolean value

Function

A function is a named and parameterized block of JavaScript code. You can define them once, and then invoke them many times. Functions are parameterized blocks of JavaScript code that we can invoke. function myFunc(x) {// Define a function named "myFunc" with parameter "x" return x + 1; // Return a value one larger than the value passed in } // Functions are enclosed in curly braces myFunc(y) // => 4: y is 3, so this invocation returns 3+1 let square = function(x) { // Functions are values and can be assigned to vars return x * x; // Compute the function's value }; // Semicolon marks the end of the assignment. square(myFunc(y)) // => 16: invoke two functions in one expression We can use => to separate the argument list from the function body, and functions defined this way are known as arrow functions. Arrow functions are most commonly used when you want to pass an unnamed function as an argument to another function. The preceding code looks like this when rewritten to use arrow functions: const myFunc = x => x + 1; // The input x maps to the output x + 1 const square = x => x * x; // The input x maps to the output x * x myFunc(y) // => 4: function invocation is the same square(myFunc(y)) // => 16 When we use functions with objects, we get methods: When functions are assigned to the properties of an object, we call them "methods." All JavaScript objects including arrays have methods: let a = []; // Create an empty array a.push(1,2,3); // The push() method adds elements to an array a.reverse(); // reverse the order of elements We can define our own methods. The "this" keyword refers to the object on which the method is defined. The points array from earlier. points.dist = function() { // Define a method to compute distance between points let p1 = this[0]; // First element of array we're invoked on let p2 = this[1]; // Second element of the "this" object let a = p2.x-p1.x; // Difference in x coordinates let b = p2.y-p1.y; // Difference in y coordinates return Math.sqrt(a*a + // The Pythagorean theorem b*b); // Math.sqrt() computes the square root }; points.dist() // => Math.sqrt(2): distance between our 2 points

Statement

JavaScript statements include conditionals and loops using the syntax of C, C++, Java, and other languages. if statement function abs(x) { // compute the absolute value. if (x >= 0) { // if statement return x; // executes this code if the comparison is true. } // This is the end of the if clause. else { // The optional else clause executes its code if return -x; // the comparison is false. } // Curly braces optional when 1 statement per clause. } // Note return statements nested inside if/else. abs(-10) === abs(10) // => true for of loop function sum(array) { // sum elements of an array let sum = 0; // Start with an initial sum of 0. for(let x of array) { // Loop over array, assigning each element to x. sum += x; // Add the element value to the sum. } // This is the end of the loop. return sum; // Return the sum. } while loop function factorial(n) { // A function to compute factorials let product = 1; // Start with a product of 1 while(n > 1) { // Repeat statements in {} while expr in () is true product *= n; // Shortcut for product = product * n; n--; // Shortcut for n = n - 1 } // End of loop return product; // Return the product } for loop function factorial2(n) { // Another version using a different loop let i, product = 1; // Start with 1 for(i=2; i <= n; i++) // Automatically increment i from 2 up to n product *= i; // Do this each time. {} not needed for 1-line loops return product; // Return the factorial }

Class

JavaScript supports an object-oriented programming style. The following code shows how to define a JavaScript class to represent 2D geometric points. Objects that are instances of this class have a single method, named distance(), that computes the distance of the point from the origin: class Point { // class names are capitalized. constructor(x, y) { // Constructor function to initialize new instances. this.x = x; // this refers to the new object being initialized. this.y = y; // store function arguments as object properties. } // no return for constructor functions. distance() { // Method to compute distance from origin to point. return Math.sqrt( // Return the square root of x square + y square. this.x * this.x + // this refers to the Point object on which this.y * this.y // the distance method is invoked. ); } } // Use the Point() constructor function with "new" to create Point objects let p = new Point(1, 1); // The geometric point (1,1). // Now use a method of the Point object p console.log(p.distance());

Variables

ECMAScript variables are loosely typed. A variable can hold any type of data. Every variable is a named placeholder for a value. There are three keywords that can be used to declare a variable: var const let var is supported for all versions and let and const were introduced in ECMAScript 6. var a = 'a'; console.log(a); let b = 'b'; console.log(b); const c = 'c' console.log(c); Output:

Note

The introduction of let and const in ECMAScript 6 bring better tooling to the Javascript language. It increases precision of declaration scope and semantics.

Don't Use var

With let and const, we no longer need to use var in our code base.

Prefer const Over let

Using const declarations allows the browser runtime to enforce constant variables. We should declare variables as const unless they know they will need to reassign its value at some point.

Use 'var' Keyword to define variables

To define a variable, use the var operator followed by the variable name, like this: var myValue; This code defines a variable named myValue that can be used to hold any value. ECMAScript supports variable initialization, so it's possible to define the variable and set its value at the same time, as in this example: var myValue = "hi"; Here, myValue is defined to hold a string value of "hi". Doing this initialization doesn't mark the variable as being a string type. It is the assignment of a value to the variable. It is still possible to not only change the value stored in the variable but also change the type of value, such as this: var myValue = "hi"; myValue = 100; // legal, but not recommended In this example, the variable myValue is first defined as having the string value "hi" and then overwritten with the numeric value 100. Although it's not recommended to switch the data type that a variable contains, it is completely valid in ECMAScript.

More than one

If you need to define more than one variable, you can do it using a single statement, separating each variable and optional initialization with a comma like this: var myValue = "hi", found = false, age = 12; Here, three variables are defined and initialized. Because ECMAScript is loosely typed, variable initializations using different data types may be combined into a single statement. Inserting line breaks and indenting the variables helps to improve readability. When you are running in strict mode, you cannot define variables named eval or arguments. Doing so results in a syntax error.

var Declaration Scope

Using the var operator to define a variable makes it local to the function scope where it was defined. For example, defining a variable inside of a function using var means that the variable is destroyed as soon as the function exits, as shown here: function test() { var myValue = "hi"; // local variable } test(); console.log(myValue); // error! Here, the myValue variable is defined within a function using var. The function test() creates the variable and assigns its value. Immediately after that, the variable is destroyed so the last line in this example causes an error.

Global

We can define a variable globally by simply omitting the var operator as follows: function test() { myValue = "hi"; // global variable } test(); console.log(myValue); // "hi" By removing the var operator from the example, the myValue variable becomes global. When the function test() is called, the variable is defined and becomes accessible outside of the function once it has been executed. Although it's possible to define global variables by omitting the var operator, this approach is not recommended. Global variables defined locally are hard to maintain and cause confusion. Strict mode throws a ReferenceError when an undeclared variable is assigned a value.

var Declaration Hoisting

When using var, the following is possible because variables declared using that keyword are hoisted to the top of the function scope: function foo() { console.log(age); var age = 26; } foo(); // undefined Output: This does not throw an error because the ECMAScript runtime technically treats it like this: function foo() { var age; console.log(age); age = 26; } foo(); // undefined Output: This is "hoisting" where the interpreter pulls all variable declarations to the top of its scope. It also allows you to use redundant var declarations without penalty: function foo() { var age = 16; var age = 26; var age = 36; console.log(age); } foo(); // 36

let Declarations

let keyword works like var with some important differences. let is block scoped, but var is function scoped. if (true) { var name = 'Javascript'; console.log(name); // Javascript } console.log(name); // Javascript if (true) { let age = 11; console.log(age); // 11 } console.log(age); // ReferenceError: age is not defined Here, the age variable cannot be referenced outside the if block because its scope does not extend outside the block. Block scope is a subset of function scope, so any scope limitations that apply to var declarations will also apply to let declarations. A let declaration does not allow for any redundant declarations within a block scope. Doing so will result in an error: var name; var name; //no error let age; let age; // SyntaxError; identifier 'age' has already been declared The JavaScript engine keeps track of identifiers used for variable declarations. Nesting identifiers behaves as you would expect with no errors because no redeclaration is occurring: var name = 'CSS'; console.log(name); // 'CSS' if (true) { var name = 'Javascript'; console.log(name); // 'Javascript' } let age = 12; console.log(age); // 12 if (true) { let age = 11; console.log(age); // 11 } The declaration redundancy errors are not a function of order, and are not affected if let is mixed with var. The two keywords specify how the variables exist inside the relevant scope. var name; let name; // SyntaxError let age; var age; // SyntaxError

let declarations does not support hoisting:

let declarations cannot be used in a way that assumes hoisting: // name is hoisted, since it is defined by var console.log(name); // undefined var name = 'Javascript'; // age is not hoisted, since it is defined by let console.log(age); // ReferenceError: age is not defined let age = 26; JavaScript engines knows that the let declarations that appear later in a block. These variables cannot be referenced before the actual declaration occurs. Any attempted references to these variables from the segment of execution that occurs before the declaration will throw a ReferenceError.

let Global Declarations

When declaring variables using let in the global context, variables will not attach to the window object as they do with var. var name = 'Javascript'; console.log(window.name); // 'Javascript' let age = 26; console.log(window.age); // undefined However, let declarations will still occur inside the global block scope, which will persist for the lifetime of the page. let age = 26; function test(){ console.log(age); } test(); Output: You must ensure your page does not attempt duplicate declarations in order to avoid throwing a SyntaxError.

let Declaration in for Loops

Prior to let, for loop definition involved using an iterator variable whose definition would go outside the loop body: for (var i = 0; i < 5; ++i) { // do loop things } console.log(i); // 5 This is no longer a problem when switching to let declarations, as the iterator variable will be scoped only to the for loop block: for (let i = 0; i < 5; ++i) { // do loop things } console.log(i); // ReferenceError: i is not defined When using var, there is a problem in the singular declaration and modification of the iterator variable: for (var i = 0; i < 5; ++i) { setTimeout(() => console.log(i), 0) } // You might expect this to console.log 0, 1, 2, 3, 4 // It will actually console.log 5, 5, 5, 5, 5 This happens because the loop exits with its iterator variable still set to the value that caused the loop to exit: 5. When the timeouts later execute, they reference this same variable, and consequently console.log its final value. When using let to declare the loop iterator, behind the scenes the JavaScript engine will actually declare a new iterator variable each loop iteration. Each setTimeout references that separate instance, and therefore it will console.log the expected value: the value of the iterator variable when that loop iteration was executed. for (let i = 0; i < 5; ++i) { setTimeout(() => console.log(i), 0) } // console.logs 0, 1, 2, 3, 4 This per-iteration declarative behavior is applicable for all styles of for loops, including for-in and for-of loops.

const Declarations

const must be initialized with a value, and that value cannot be redefined after declaration. Attempting to modify a const variable will result in a runtime error. const age = 26; age = 36; // TypeError: assignment to a constant const still disallows redundant declaration const name = 'Javascript'; const name = 'CSS'; // SyntaxError const is still scoped to blocks const name = 'Javascript'; if (true) { const name = 'CSS'; } console.log(name); // Javascript The const declaration is only enforced with respect to the reference to the variable that it points to. If a const variable references an object, it does not violate the const constraints to modify properties inside that object. const person = {}; person.name = 'Javascript'; // ok You cannot use const to declare for loop iterators: for (const i = 0; i < 10; ++i) {} // TypeError: assignment to constant variable You can use const to declare a for loop variable that is not modified. This is especially relevant in the case of for-of and for-in loops: Define j as constant inside for loop let i = 0; for (const j = 7; i < 5; ++i) { console.log(j); } Output: Use const in for-in loop for (const key in {a: 1, b: 2}) { console.log(key); } Output: Use const in for-of loop for (const value of [1,2,3,4,5]) { console.log(value); } Output:

Data Types

There are six simple data types or primitive types in ECMAScript: undefined null, Boolean, Number, String, Symbol. There is also one complex data type called Object. Object is an unordered list of name-value pairs. let a = undefined; console.log(a); a = null; console.log(a); a = true; console.log(a); a = 123.123; console.log(a); a = 'string'; console.log(a); a = Symbol(); console.log(a); Output:

Data Type Overview and Definitions

JavaScript types can be divided into two categories: primitive types and object types.

Primitive types

JavaScript's primitive types include numbers, strings, and booleans. The special JavaScript values null and undefined are primitive values, but they are not numbers, strings, or booleans. ES6 adds a new special-purpose type, known as Symbol, that enables the definition of language extensions without harming backward compatibility.

Object

Any JavaScript value that is not a number, a string, a boolean, a symbol, null, or unde fined is an object. An object is a collection of properties where each property has a name and a value. An ordinary JavaScript object is an unordered collection of named values.

Array

The language also defines a special kind of object, known as an array, that represents an ordered collection of numbered values. The JavaScript language includes special syntax for working with arrays, and arrays have some special behavior that distinguishes them from ordinary objects.

Other

JavaScript defines a number of other useful object types. A Set object represents a set of values. A Map object represents a mapping from keys to values. Various "typed array" types facilitate operations on arrays of bytes and other binary data. The RegExp type represents String patterns and enables matching, searching, and replacing operations on strings. The Date type represents dates and times. Error and its subtypes represent errors that can arise when executing JavaScript code. JavaScript functions and classes are not just part of the language syntax, they are values that can be manipulated by JavaScript programs.

Note

JavaScript's object types are mutable and its primitive types are immutable. JavaScript liberally converts values from one type to another. If a program expects a string, for example, and you give it a number, it will automatically convert the num ber to a string for you. And if you use a non-boolean value where a boolean is expected, JavaScript will convert accordingly.

typeof Operator to check data type

The typeof operator determine the data type in Javascript. Using the typeof operator on a value returns one of the following strings: "undefined" if the value is undefined "boolean" if the value is a Boolean "string" if the value is a string "number" if the value is a number "object" if the value is an object (other than a function) or null "function" if the value is a function "symbol" if the value is a Symbol

Example

The typeof operator is called like this: let message = "some string"; console.log(typeof message); // "string" console.log(typeof(message)); // "string" console.log(typeof 5); // "number" In this example, both a variable message and a numeric literal are passed into the typeof operator. typeof is an operator and not a function, no parentheses are required although they can be used.

Note

typeof might return a confusing but technically correct value. Calling typeof null returns a value of "object", as the special value null is considered to be an empty object reference. Technically, functions are considered objects in ECMAScript and don't represent another data type.

undefined Type

The undefined type has only one value, which is the special value undefined. When a variable is declared using var or let but not initialized, it is assigned the value of undefined as follows: let message; console.log(message == undefined); // true In this example, the variable message is declared without initializing it. When compared with the literal value of undefined, the two are equal. This example is identical to the following: let message = undefined; console.log(message == undefined); // true Here the variable message is explicitly initialized to be undefined. This is unnecessary because, by default, any uninitialized variable gets the value of undefined. You should never explicitly set a variable to be undefined. The literal undefined value is provided for comparison. A variable containing the value of undefined is different from a variable that hasn't been defined at all. Consider the following: let message; // this variable is declared // but has a value of undefined console.log(message); // "undefined" console.log(age); // causes an error In this example, the first console.log displays the variable message, which is "undefined". In the second console.log, an undeclared variable called age is passed into the console.log() function, which causes an error because the variable hasn't been declared. The typeof operator returns "undefined" when called on an uninitialized variable, but it also returns "undefined" when called on an undeclared variable, which can be a bit confusing. Consider this example: let message; // this variable is declared but has a value of undefined console.log(typeof message); // "undefined" console.log(typeof age); // "undefined" In both cases, calling typeof on the variable returns the string "undefined". Logically, this makes sense because no real operations can be performed with either variable even though they are technically different. We should always initialize variables. That way, when typeof returns "undefined", you'll know that it's because a given variable hasn't been declared rather than was simply not initialized.

falsy

The value undefined is falsy and you can use if to check it. There are many other possible values as falsy, so be careful when using if statement to test undefined: let message; // this variable is declared but has a value of undefined // 'age' is not declared if (message) { // This block will not execute } if (!message) { // This block will execute } if (age) { // This will throw an error }

null Type

The Null type has only one value: the special value null. Logically, a null value is an empty object pointer, which is why typeof returns "object" when it's passed a null value in the following example: let myValue = null; console.log(typeof myValue); // "object" When defining a variable that is meant to later hold an object, we should initialize the variable to null as opposed to anything else. You can explicitly check for the value null to determine if the variable has been filled with an object reference at a later time, such as in this example: let myValue = null; if (myValue != null) { // do something with myValue } The value undefined is a derivative of null, so ECMA-262 defines them to be superficially equal as follows: console.log(null == undefined); // true Using the equality operator (==) between null and undefined always returns true.

falsy

The null type is falsy; therefore, you can use if statement to check it. let myValue = null; let age; if (myValue) { // This block will not execute } if (!myValue) { // This block will execute } if (age) { // This block will not execute } if (!age) { // This block will execute }

Boolean Type

The Boolean type has only two literal values: true and false. These values are distinct from numeric values, so true is not equal to 1, and false is not equal to 0. Assignment of Boolean values to variables is as follows: let found = true; let lost = false; The Boolean literals true and false are case-sensitive, so True and False are valid as identifiers but not as Boolean values. let found = true; let lost = false; console.log(found === 0); //false console.log(found === 1); //false console.log(lost === 0); //false console.log(lost === 1); //false console.log(found == 0); //false console.log(found == 1); //true console.log(lost == 0); //true console.log(lost == 1); //false

Convert values to Boolean using Boolean() convert function

All types of values have Boolean equivalents in ECMAScript. To convert a value into its Boolean equivalent, the special Boolean() casting function is called, like this: let message = "hi!"; let messageAsBoolean = Boolean(message); In this example, the string message is converted into a Boolean value and stored in messageAsBoolean. The Boolean() casting function can be called on any type of data and will always return a Boolean value. The rules for when a value is converted to true or false depend on the data type as much as the actual value. The following table outlines the various data types and their specific conversions.
Data Type Values Converted To True Values Converted To False
Boolean true false
String Any nonempty string "" (empty string)
Number Any nonzero number
(including infinity)
0, NaN
Object Any object null
Undefined n/a undefined
The flow-control statements, such as the if statement, automatically perform this Boolean conversion, as shown here: let message = "hi!"; if (message) { console.log("Value is true"); } In this example, the console.log will be displayed because the string message is automatically converted into its Boolean equivalent (true). It's important to understand what variable you're using in a flow-control statement because of this automatic conversion.

Integer Literal Octal and hexadecimal value

JavaScript's primary numeric type, Number, is used to represent integers and to approximate real numbers. ECMAScript Number uses the IEEE-754 format to represent both integers and floating-point values. The JavaScript number format allows you to exactly represent all integers between -9,007,199,254,740,992 and 9,007,199,254,740,992, inclusive. To support the various types of numbers, there are several different number literal formats.

Literal

The most basic number literal format is that of a decimal integer, which can be entered directly as shown here: let intNum = 55; // integer In a JavaScript program, a base-10 integer is written as a sequence of digits. For example: 0 3 10000000

Octal

Integers can also be represented as either octal (base 8) or hexadecimal (base 16) literals. For an octal literal, the first digit must be a zero (0) followed by a sequence of octal digits (numbers 0 through 7). If a number out of this range is detected in the literal, then the leading zero is ignored and the number is treated as a decimal, as in the following examples: let octalNum1 = 070; // octal for 56 let octalNum2 = 079; // invalid octal - interpreted as 79 let octalNum3 = 08; // invalid octal - interpreted as 8 Octal literals are invalid when running in strict mode and will cause the JavaScript engine to throw a syntax error.

hexadecimal

To create a hexadecimal literal, you must make the first two characters 0x (case insensitive), followed by any number of hexadecimal digits (0 through 9, and A through F). Letters may be in uppercase or lowercase. Here's an example: let hexNum1 = 0xA; // hexadecimal for 10 let hexNum2 = 0x1f; // hexadecimal for 31 Numbers created using octal or hexadecimal format are treated as decimal numbers in all arithmetic operations.

Binary

In ES6 and later, you can also express integers in binary (base 2) or octal (base 8) using the prefixes 0b and 0o (or 0B and 0O): 0b10101 // => 21: (1*16 + 0*8 + 1*4 + 0*2 + 1*1) 0o377 // => 255: (3*64 + 7*8 + 7*1)

Floating-Point Values

To define a floating-point value, you must include a decimal point and at least one number after the decimal point. Although an integer is not necessary before a decimal point, it is recommended. Here are some examples: let floatNum1 = 1.1; let floatNum2 = 0.1; let floatNum3 = .1; // valid, but not recommended You can use underscores within numeric literals to break long literals up into chunks that are easier to read: let billion = 1_000_000_000; // Underscore as a thousands separator. let bytes = 0x89_AB_CD_EF; // As a bytes separator. let bits = 0b0001_1101_0111; // As a nibble separator. let fraction = 0.123_456_789; // Works in the fractional part, too. When there is no digit after the decimal point, the number becomes an integer. If the number being represented is a whole number (such as 1.0), it will be converted into an integer, as in this example: let floatNum1 = 1.; // missing digit after decimal - interpreted as integer 1 let floatNum2 = 10.0; // whole number - interpreted as integer 10

E-notation

Javascript floating-point values can be represented using e-notation. E-notation is used to indicate a number that should be multiplied by 10 raised to a given power. The format of e-notation in ECMAScript is to have a number, integer or floating-point, followed by an uppercase or lowercase letter E, followed by the power of 10 to multiply by. Consider the following: let floatNum = 3.125e7; // equal to 31250000 In this example, floatNum is equal to 31,250,000 and it is represented in a more compact form using e-notation. The notation says, "Take 3.125 and multiply it by 10000000." E-notation can also be used to represent very small numbers, such as 0.00000000000000003, which can be written more succinctly as 3e-17. By default, ECMAScript converts any floating-point value with at least six zeros after the decimal point into e-notation (for example, 0.0000003 becomes 3e-7).

Accuracy

Floating-point values are accurate up to 17 decimal places but are far less accurate in arithmetic computations than whole numbers. For instance, adding 0.1 and 0.2 yields 0.30000000000000004 instead of 0.3. These small rounding errors make it difficult to test for specific floating-point values. Consider this example: const a = 0.1; const b = 0.2; if (a + b == 0.3) { // avoid! console.log("You got 0.3."); }else{ console.log("not 0.3."); } Output: Here, the sum of two numbers is tested to see if it's equal to 0.3. You should never test for specific floating-point values.

Note

The rounding errors are caused by how the floating-point arithmetic is done in IEEE-754-based numbers and is not unique to ECMAScript. Other languages that use the same format have the same issues.

Number Range of Values, Infinity, and negative infinity

The smallest number that can be represented in ECMAScript is stored in Number.MIN_VALUE and is 5e-324 on most browsers; the largest number is stored in Number.MAX_VALUE and is 1.7976931348623157e+308 on most browsers. If a calculation results in a number that cannot be represented by JavaScript's numeric range, the number automatically gets the special value of Infinity. Any negative number that can't be represented is -Infinity (negative infinity), and any positive number that can't be represented is Infinity (positive infinity). If a calculation returns either positive or negative Infinity, that value cannot be used in any further calculations. To determine if a value is finite, there is the isFinite() function. This function returns true only if the argument is between the minimum and the maximum values, as in this example: let result = Number.MAX_VALUE + Number.MAX_VALUE; console.log(isFinite(result)); // false You can get the values of positive and negative Infinity by accessing *Number.NEGATIVE _INFINITY* and *Number.POSITIVE _INFINITY*. These properties contain the values -Infinity and Infinity, respectively.

Float value NaN, Not a Number

There is a special numeric value called NaN, short for Not a Number, which indicates the returned value is Not a Number. For example, in ECMAScript, dividing a number by 0 returns NaN, which allows other processing to continue. The value NaN has a couple of unique properties. First, any operation involving NaN always returns NaN, For example NaN /20. Second, NaN is not equal to any value, including NaN. For example, the following returns false: console.log(NaN == NaN); // false

isNaN()

ECMAScript provides the isNaN() function. isNaN() function accepts a single argument to determine if the value is "not a number". When a value is passed into isNaN(), an attempt is made to convert it into a number. Some nonnumerical values convert into numbers directly, such as the string "10" or a Boolean value. Any value that cannot be converted into a number causes the function to return true. Consider the following: console.log(isNaN(NaN)); // true console.log(isNaN(10)); // false - 10 is a number console.log(isNaN("10")); // false - can be converted to number 10 console.log(isNaN("demo2s.com")); // true - cannot be converted to a number console.log(isNaN(true)); // false - can be converted to number 1 This example tests five different values. The first test is on the value NaN itself, which returns true. The next two tests use numeric 10 and the string "10", which both return false because the numeric value for each is 10. The string "demo2s.com" cannot be converted into a number, so the function returns true. The Boolean value of true can be converted into the number 1, so the function returns false. isNaN() can be applied to objects. In that case, the object's valueOf() method is first called to determine if the returned value can be converted into a number. If not, the toString() method is called and its returned value is tested as well.

Number Conversions with Number() function, convert values into numbers

There are three functions to convert nonnumeric values into numbers: the Number() casting function, the parseInt() function, and the parseFloat() function. The first function, Number(), can be used on any data type; the other two functions are used specifically for converting strings to numbers. The Number() function performs conversions based on these rules: 1. When applied to Boolean values, true and false get converted into 1 and 0, respectively. 2. When applied to numbers, the value is returned. 3. When applied to null, Number() returns 0. 4. When applied to undefined, Number() returns NaN. 5. When applied to strings, the following rules are applied: If the string contains only numeric characters, optionally preceded by a plus or minus sign, it is always converted to a decimal number, so Number("1") becomes 1, Number("123") becomes 123, and Number("011") becomes 11. Leading zeros are ignored. If the string contains a valid floating-point format, such as "1.1", it is converted into the appropriate floating-point numeric value. Leading zeros are ignored. If the string contains a valid hexadecimal format, such as "0xf", it is converted into an integer that matches the hexadecimal value. If the string is empty, it is converted to 0. If the string contains anything other than these previous formats, it is converted into NaN. 6. When applied to objects, the valueOf() method is called and the returned value is converted based on the previously described rules. If that conversion results in NaN, the toString() method is called and the rules for converting strings are applied. . Here are some concrete examples: let num1 = Number("hi!"); // NaN let num2 = Number(""); // 0 let num3 = Number("00002");// 2 let num4 = Number(true); // 1 In these examples, the string "hi!" is converted into NaN because it has no corresponding numeric value, and the empty string is converted into 0. The string "00002" is converted to the number 2 because the initial zeros are ignored. Last, the value true is converted to 1.

Convert String to Number with parseInt()

parseInt() function is usually used when you are dealing with integers. The parseInt() function examines the string to see if it matches a number pattern. Leading white space in the string is ignored until the first non-white space character is found. If this first character isn't a number, the minus sign, or the plus sign, parseInt() always returns NaN, which means the empty string returns NaN. If the first character is a number, plus, or minus, then the conversion goes on to the second character and continues on until either the end of the string is reached or a nonnumeric character is found. For instance, "1234demo" is converted to 1234 because "demo" is completely ignored. "22.5" will be converted to 22 because the decimal is not a valid integer character. If the first character in the string is a number, the parseInt() function also recognizes the various integer formats: decimal, octal, and hexadecimal. The string begins with "0x" is interpreted as a hexadecimal integer; if it begins with "0" followed by a number, it is interpreted as an octal value. Here are some conversion examples to illustrate what happens: let num1 = parseInt("1234demo"); // 1234 let num2 = parseInt(""); // NaN let num3 = parseInt("0xA"); // 10 - hexadecimal let num4 = parseInt(2.5); // 2 let num5 = parseInt("70"); // 70 - decimal let num6 = parseInt("0xf"); // 15 - hexadecimal parseInt("3 asdf ") // => 3 parseFloat(" 3.14 meters") // => 3.14 parseInt("-12.34") // => -12 parseInt("0xFF") // => 255 parseInt("0xff") // => 255 parseInt("-0XFF") // => -255 parseFloat(".1") // => 0.1 parseInt("0.1") // => 0 parseInt(".1") // => NaN: integers can't start with "." parseFloat("$72.47") // => NaN: numbers can't start with "$"

radix

parseInt() provides a second argument: the radix. If you know that the value you're parsing is in hexadecimal format, you can pass in the radix 16 as a second argument and ensure that the correct parsing will occur, as shown here: let num = parseInt("0xAF", 16); // 175 In fact, by providing the hexadecimal radix, you can leave off the leading "0x" and the conversion will work as follows: let num1 = parseInt("AF", 16); // 175 let num2 = parseInt("AF"); // NaN In this example, the first conversion occurs correctly, but the second conversion fails. The radix is passed in on the first line, telling parseInt() that it will be passed a hexadecimal string; the second line sees that the first character is not a number and stops automatically. Passing in a radix can change the outcome of the conversion. Consider the following: let num1 = parseInt("10", 2); // 2 - parsed as binary let num2 = parseInt("10", 8); // 8 - parsed as octal let num3 = parseInt("10", 10); // 10 - parsed as decimal let num4 = parseInt("10", 16); // 16 - parsed as hexadecimal parseInt("11", 2) // => 3: (1*2 + 1) parseInt("ff", 16) // => 255: (15*16 + 15) parseInt("zz", 36) // => 1295: (35*36 + 35) parseInt("077", 8) // => 63: (7*8 + 7) parseInt("077", 10) // => 77: (7*10 + 7) We should always include a radix to avoid errors. Most of the time you'll be parsing decimal numbers, so it's good to always include 10 as the second argument.

Convert String to Number with parseFloat()

The parseFloat() function looks at each character starting in position 0. It continues to parse the string until it reaches either the end of the string or a character that is invalid in a floating-point number. This means that a decimal point (.) is valid the first time it appears, but a second decimal point is invalid and the rest of the string is ignored, resulting in "2.34.5" being converted to 2.34. parseFloat() always ignores the initial zeros. parseFloat() recognizes any of the floating-point formats. Hexadecimal numbers always become 0 in parseFloat(). Because parseFloat() parses only decimal values, there is no radix mode. If the string represents a whole number without decimal point or only a zero after the decimal point, parseFloat() returns an integer. Here are some examples: let num1 = parseFloat("1234demo"); // 1234 - integer let num2 = parseFloat("0xA"); // 0 let num3 = parseFloat("2.5"); // 2.5 let num4 = parseFloat("2.34.5"); // 2.34 let num5 = parseFloat("0907.6"); // 907.6 let num6 = parseFloat("3.125e7"); // 31250000

Number Format

Formatting and parsing numbers are common tasks in computer programs. JavaScript has specialized functions and methods that provide more precise control over number-to-string and string-to-number conversions. The toString() method defined by the Number class accepts an optional argument that specifies a radix, or base, for the conversion. If you do not specify the argument, the conversion is done in base 10. However, you can also convert numbers in other bases (between 2 and 36). For example: let n = 17; let binary = "0b" + n.toString(2); // binary == "0b10001" let octal = "0o" + n.toString(8); // octal == "0o21" let hex = "0x" + n.toString(16); // hex == "0x11" You may want to convert numbers to strings in ways that give you control over the number of decimal places or the number of significant digits in the output, or you may want to control whether exponential notation is used. The Number class defines three methods for these kinds of number-to-string conversions. toFixed() converts a number to a string with a specified number of digits after the decimal point. It never uses exponential notation. toExponential() converts a number to a string using exponential notation, with one digit before the decimal point and a specified number of digits after the decimal point. toPrecision() converts a number to a string with the number of significant digits you specify. It uses exponential notation if the number of significant digits is not large enough to display the entire integer portion of the number. Note that all three methods round the trailing digits or pad with zeros as appropriate. Consider the following examples: let n = 123456.789; n.toFixed(0) // => "123457" n.toFixed(2) // => "123456.79" n.toFixed(5) // => "123456.78900" n.toExponential(1) // => "1.2e+5" n.toExponential(3) // => "1.235e+5" n.toPrecision(4) // => "1.235e+5" n.toPrecision(7) // => "123456.8" n.toPrecision(10) // => "123456.7890"

Object Type

Objects in ECMAScript are created by using the new operator followed by the name of the object type to create. Developers create their own objects by creating instances of the Object type and adding properties and/or methods to it, as shown here: let o = new Object(); ECMAScript requires parentheses to be used only when providing arguments to the constructor. If there are no arguments, as in the following example, then the parentheses can be omitted safely. It is not recommended to do this. let o = new Object; // legal, but not recommended The Object type in ECMAScript is the base from which all other objects are derived. All of the properties and methods of the Object type are also present on other, more specific objects. Each Object instance has the following properties and methods:
Method Description
constructor The function that was used to create the object.
In the previous example, the constructor is the Object() function.
hasOwnProperty(propertyName ) Indicates if the given property exists on the object instance (not on the prototype). The property name must be specified as a string (for example, o.hasOwnProperty("name")).
isPrototypeof(object) Determines if the object is a prototype of another object.
propertyIsEnumerable(propertyName ) Indicates if the given property can be enumerated using the for-in statement (discussed later in this chapter). As with hasOwnProperty(), the property name must be a string.
toLocaleString() Returns a string representation of the object that is appropriate for the locale of execution environment.
toString() Returns a string representation of the object.
valueOf() Returns a string, number, or Boolean equivalent of the object. It often returns the same value as toString().
Because Object is the base for all objects in ECMAScript, every object has these base properties and methods.

Arbitrary Precision Integers with BigInt

BigInt is a numeric type whose values are integers. The type was added to JavaScript mainly to allow the representation of 64-bit integers. BigInt values can have thousands or even millions of digits.

Literal

BigInt literals are written as a string of digits followed by a lowercase letter n. By default, the are in base 10, but you can use the 0b, 0o, and 0x prefixes for binary, octal, and hexadecimal BigInts: 1234n // A not-so-big BigInt literal 0b111111n // A binary BigInt 0o7777n // An octal BigInt 0x8000000000000000n // => 2n**63n: A 64-bit integer You can use BigInt() as a function for converting regular JavaScript numbers or strings to BigInt values: BigInt(Number.MAX_SAFE_INTEGER) // => 9007199254740991n //from string let string = "1" + "0".repeat(100); // 1 followed by 100 zeros. BigInt(string) // => 10n**100n: one googol Arithmetic with BigInt values works like arithmetic with regular JavaScript numbers, except that division drops any remainder and rounds down (toward zero): 1000n + 2000n // => 3000n 3000n - 2000n // => 1000n 2000n * 3000n // => 6000000n 3000n / 997n // => 3n: the quotient is 3 3000n % 997n // => 9n: and the remainder is 9 (2n ** 131071n) - 1n // A Mersenne prime with 39457 decimal digits Although the standard +, -, *, /, %, and ** operators work with BigInt, you may not mix operands of type BigInt with regular number operands. Comparison operators, by contrast, do work with mixed numeric types: 1 < 2n // => true 2 > 1n // => true 0 == 0n // => true 0 === 0n // => false: the === checks for type equality as well The bitwise operators work with BigInt operands. None of the functions of the Math object accept BigInt operands, however.

Primitive And Reference Values

ECMAScript variables has two different types of data: primitive values and reference values.

Primitive values

Primitive values are simple atomic pieces of data, while reference values are objects that may be made up of multiple values. When a value is assigned to a variable, the JavaScript engine must determine if it's a primitive or a reference value. The six primitive types are: undefined, null, Boolean, Number, String, and Symbol. These variables are accessed by value, because you are manipulating the actual value stored in the variable.

Reference values

Reference values are objects stored in memory. JavaScript does not permit direct access of memory locations, so direct manipulation of the object's memory space is not allowed. When you manipulate an object, you're really working on a reference to that object rather than the actual object itself. For this reason, such values are said to be accessed by reference.

Dynamic Properties on Primitive And Reference Values

When you work with reference values, you can add, change, or delete properties and methods at any time. Consider this example: let person = new Object(); person.name = "CSS"; console.log(person.name); // "CSS" Here, an object is created and stored in the variable person. Next, a property called name is added and assigned the string value of "CSS". The new property is accessible until the object is destroyed or the property is explicitly removed. Primitive values can't have properties added to them even though attempting to do so won't cause an error. Here's an example: let name = "CSS"; name.age = 12; console.log(name.age); // undefined Here, a property called age is defined on the string name and assigned a value of 12. On the next line, however, the property is gone. Only reference values can have properties defined dynamically for later use. Note that the instantiation of a primitive type can be accomplished using only the primitive literal form. If you were to use the new keyword, JavaScript will create an Object type, but one that behaves like a primitive. Here's an example to distinguish between the two: let name1 = "CSS"; let name2 = new String("Javascript"); name1.age = 27; name2.age = 26; console.log(name1.age); // undefined console.log(name2.age); // 26 console.log(typeof name1); // string console.log(typeof name2); // object

Copying Values on Primitive And Reference Values

Javascript primitive and reference values act differently when copied from one variable to another.

Primitive value

When a primitive value is assigned from one variable to another, the value stored on the variable object is created and copied into the location for the new variable. Consider the following example: let num1 = 5; let num2 = num1; Here, num1 contains the value of 5. When num2 is initialized to num1, it also gets the value of 5. This value is completely separate from the one that is stored in num1 because it's a copy of that value. Each of these variables can now be used separately with no side effects.

Reference value

When a reference value is assigned from one variable to another, the value stored on the variable object is copied into the location for the new variable. This value is a pointer to an object variable object after copy stored on the heap. Once the operation is complete, two variables point to exactly the same object, so changes to one are reflected on the other, as in the following example: let obj1 = new Object(); let obj2 = obj1; obj1.name = "CSS"; console.log(obj2.name); // "CSS" In this example, the variable obj1 is filled with a new instance of an object. This value is then copied into obj2, meaning that both variables are now pointing to the same object. When the property name is set on obj1, it can later be accessed from obj2 because they both point to the same object.

Argument Passing on Primitive And Reference Values

All function arguments in ECMAScript are passed by value. The value outside of the function is copied into an argument on the inside of the function the same way a value is copied from one variable to another. If the value is primitive, then it acts just like a primitive variable copy, and if the value is a reference, it acts just like a reference variable copy.

Pass by value vs Pass by reference

When an argument is passed by value, the value is copied into a local variable. When an argument is passed by reference, the location of the value in memory is stored into a local variable, which means that changes to the local variable are reflected outside of the function. Pass by reference is not supported by Javascript.

Example

Consider the following example: function addTen(num) { num += 10; return num; } let count = 20; let result = addTen(count); console.log(count); // 20 - no change console.log(result); // 30 Here, the function addTen() has an argument, num, which is essentially a local variable. When called, the variable count is passed in as an argument. This variable has a value of 20, which is copied into the argument num for use inside of addTen(). Within the function, the argument num has its value changed by adding 10, but this doesn't change the original variable count that exists outside of the function. The argument num and the variable count are not related and they just have the same value. If num had been passed by reference (which cannot be done by Javascript), then the value of count would have changed to 30 to reflect the change made inside the function.

Pass reference type

For reference type value such as Javascript objects, for example: function setName(obj) { obj.name = "CSS"; } let person = new Object(); setName(person); console.log(person.name); // "CSS" In this code, an object is created and stored in the variable person. This object is then passed into the setName() method, where it is copied into obj. Inside the function, obj and person both point to the same object. The result is that obj is accessing an object by reference, even though it was passed into the function by value. When the name property is set on obj inside the function, this change is reflected outside the function, because the object that it points to exists globally on the heap.

NOT passed by reference

Javascript object is NOT passed by reference. To prove that objects are passed by value, consider the following modified code: function setName(obj) { obj.name = "CSS"; obj = new Object(); obj.name = "HTML"; } let person = new Object(); setName(person); console.log(person.name); // "CSS" This example added two lines to redefine obj as a new object with a different name. When person is passed into setName(), its name property is set to "CSS". Then the variable obj is set to be a new object and its name property is set to "HTML". If person were passed by reference, then person would automatically be changed to point to the object whose name is "HTML". However, when person.name is accessed again, its value is "CSS", indicating that the original reference remained intact even though the argument's value changed inside the function. When obj is overwritten inside the function, it becomes a pointer to a local object. That local object is destroyed as soon as the function finishes executing. You can think function arguments in ECMAScript as local variables.

Determining Type using instanceof operator

The typeof operator can determine if a variable is a primitive type. We can use typeof operator to determine if a variable is a string, number, Boolean, or undefined. If the value is an object or null, then typeof returns "object", as in this example: let s = "CSS"; let b = true; let i = 2; let u; let n = null; let o = new Object(); console.log(typeof s); // string console.log(typeof i); // number console.log(typeof b); // boolean console.log(typeof u); // undefined console.log(typeof n); // object console.log(typeof o); // object typeof operator has little use for reference values.

instanceof

instanceof operator can check object type. ECMAScript instanceof operator is used with the following syntax: result = variable instanceof constructor The instanceof operator returns true if the variable is an instance of the given reference type. Consider this example: console.log(person instanceof Object); // is the variable person an Object? console.log(colors instanceof Array); // is the variable colors an Array? console.log(pattern instanceof RegExp); // is the variable pattern a RegExp? All reference values, by definition, are instances of Object, so the instanceof operator always returns true when used with a reference value and the Object constructor. Similarly, if instanceof is used with a primitive value, it will always return false, because primitives aren't objects.

Execution Context And Scope

The JavaScript execution context of a variable or function defines what other data it has access to, as well as how it should behave. Each execution context has an associated variable object upon which all of its defined variables and functions exist. This object is not accessible by code but is used behind the scenes to handle data.

Global

The global execution context is the outermost one. Depending on the host environment for an ECMAScript implementation, the object representing this context may differ. In web browsers, the global context is said to be that of the window object, so all global variables and functions defined with var are created as properties and methods on the window object. Declarations using let and const at the top level are not defined in the global context, but they are resolved identically on the scope chain. When an execution context has executed all of its code, it is destroyed. The global context isn't destroyed until the application exits, such as when a web page is closed or a web browser is shut down.

Function

Each function call has its own execution context. Whenever code execution flows into a function, the function's context is pushed onto a context stack. After the function has finished executing, the stack is popped, returning control to the previously executing context.

Scope

When code is executed in a context, a scope chain of variable objects is created. The scope chain provides ordered access to all variables and functions that an execution context has access to. The top of the scope chain is the variable object of the context whose code is executing. If the context is a function, then the activation object is used as the variable object. This pattern continues until the global context is reached; the global context's variable object is always the last of the scope chain. Identifiers are resolved by navigating the scope chain in search of the identifier name. The search always begins at the front of the chain and proceeds to the back until the identifier is found. If the identifier isn't found, typically an error occurs. Consider the following code: var color = "blue"; function changeValue() { if (color === "blue") { color = "red"; } else { color = "blue"; } } changeValue(); In this simple example, the function changeValue() has a scope chain with two objects in it: its own variable object, where the arguments object is defined, and the global context's variable object. The variable color is therefore accessible inside the function, because it can be found in the scope chain.

Local

The locally defined variables can be used interchangeably with global variables in a local context. Here's an example: var color = "blue"; function changeValue() { let anotherValue = "red"; function swapValues() { let tempValue = anotherValue; anotherValue = color; color = tempValue; // color, anotherValue, and tempValue are all accessible here } // color and anotherValue are accessible here, but not tempValue swapValues(); } // only color is accessible here changeValue(); There are three execution contexts in this code: global context, the local context of changeValue(), and the local context of swapValues(). The global context has one variable, color, and one function, changeValue(). The local context of changeValue() has one variable named anotherValue and one function named swapValues(), but it can also access the variable color from the global context. The local context of swapValues() has one variable, named tempValue, that is accessible only within that context. Neither the global context nor the local context of swapValues() has access to tempValue. Within swapValues(), though, the variables of the other two contexts are fully accessible because they are parent execution contexts. The connection between the contexts is linear and ordered. Each context can search up the scope chain for variables and functions, but no context can search down the scope chain into another execution context. There are three objects in the scope chain for the local context of swapValues(): the swapValues() variable object, the variable object from changeValue(), and the global variable object. The local context of swapValues() begins its search for variable and function names in its own variable object before moving along the chain. The scope chain for the changeValue() context has only two objects: its own variable object and the global variable object. This means that it cannot access the context of swapValues(). NOTE Function arguments are considered to be variables and follow the same access rules as any other variable in the execution context.

Execution Context And Scope Chain Augmentation

Even though there are only two primary types of execution contexts, global and function, there are other ways to augment the scope chain. Certain statements cause a temporary addition to the front of the scope chain that is later removed after code execution. There are two times when this occurs, specifically when execution enters either of the following: The catch block in a try-catch statement A with statement Both of these statements add a variable object to the front of the scope chain. For the with statement, the specified object is added to the scope chain; for the catch statement, a new variable object is created and contains a declaration for the thrown error object. Consider the following: function buildUrl() { let qs = "?debug=true"; with(location){ let url = href + qs; } return url; } In this example, the with statement is acting on the location object, so location itself is added to the front of the scope chain. There is one variable, qs, defined in the buildUrl() function. When the variable href is referenced, it's actually referring to location.href, which is in its own variable object. When the variable qs is referenced, it's referring to the variable defined in buildUrl(), which is in the function context's variable object. Inside the with statement is a variable declaration for url, which becomes part of the function's context and can, therefore, be returned as the function value.

Function Scope Declaration Using var

When a variable is declared using var, it is automatically added to the most immediate context available. In a function, the most immediate one is the function's local context; in a with statement, the most immediate is the function context. If a variable is initialized without first being declared, it gets added to the global context automatically, as in this example: function add(num1, num2) { var sum = num1 + num2; return sum; } let result = add(10, 20); // 30 console.log(sum); // causes an error: sum is not a valid variable Here, the function add() defines a local variable named sum that contains the result of an addition operation. This value is returned as the function value, but the variable sum isn't accessible outside the function. If the var keyword is omitted from this example, sum becomes accessible after add() has been called, as shown here: function add(num1, num2) { sum = num1 + num2; return sum; } let result = add(10, 20); // 30 console.log(sum); // 30 Here, the variable sum is initialized to a value without ever having been declared using var. When add() is called, sum is created in the global context and continues to exist even after the function has completed, allowing you to access it later. It's advisable to always declare variables before initializing them. In strict mode, initializing variables without declaration causes an error. A var declaration will be brought to the top of the function or global scope and before any existing code inside it. This is referred to as "hoisting". This allows you to safely use a hoisted variable anywhere in the same scope without consideration for whether or not it was declared yet. Here is an example of two equivalent code in the global scope: var name = "css"; // This is equivalent to: name = 'css'; var name; Here is an example of two equivalent functions: function fn1() { var name = 'css'; } // This is equivalent to: function fn2() { var name; name = 'css'; } You can prove to yourself that a variable is hoisted by inspecting it before its declaration. The hoisting of the declaration means you will see undefined instead of ReferenceError: console.log(name); // undefined var name = 'css'; function() { console.log(name); // undefined var name = 'css'; }

Block Scope Declaration Using let

ES6 let operates much in the same way as var, but it is scoped at the block level in JavaScript. Block scope is defined as the nearest set of enclosing curly braces {}. This means if blocks, while blocks, function blocks, and even standalone blocks will be the extent of the scope of any variable declared with let. if (true) {/*w w w . d e m o2 s . c o m*/ let a; } console.log(a); // ReferenceError: a is not defined while (true) { let b; } console.log(b); // ReferenceError: b is not defined function foo() { let c; } console.log(c); // ReferenceError: c is not defined // This is not an object literal, this is a standalone block. { let d; } console.log(d); // ReferenceError: d is not defined let cannot be declared twice inside the same block scope. Duplicate var declarations are simply ignored; duplicate let declarations throw a SyntaxError. var a; var a; // No errors thrown { let b; let b; } // SyntaxError: Identifier 'b' has already been declared The behavior of let is especially useful when using iterators inside loops. Iterator declarations using var will bleed outside the loop after it completes, which is frequently a very undesirable behavior. Consider these two examples: for (var i = 0; i < 10; ++i) {} console.log(i); // 10 for (let j = 0; j < 10; ++j) {} console.log(j); // ReferenceError: j is not defined

Constant Declaration Using const

ES6 introduces const as companion to let. A variable declared using const must be initialized to some value. Once declared, it cannot be reassigned to a new value at any point in its lifetime. const a; // SyntaxError: Missing initializer in const declaration const b = 3; console.log(b); // 3 b = 4; // TypeError: Assignment to a constant variable Apart from its const rule enforcement, const variables behave identically to let variables: if (true) { const a = 0; } console.log(a); // ReferenceError: a is not defined while (true) { const b = 1; } console.log(b); // ReferenceError: b is not defined function foo() { const c = 2; } console.log(c); // ReferenceError: c is not defined { const d = 3; } console.log(d); // ReferenceError: d is not defined The const declaration only applies to the top-level primitive or object. A const variable assigned to an object cannot be reassigned to another reference value, but the keys inside that object are not protected. const o1 = {}; o1 = {}; // TypeError: Assignment to a constant variable; const o2 = {}; o2.name = 'css'; console.log(o2.name); // 'css' If you wish to make the entire object immutable, you can use Object.freeze(), although attempted property assignment will not raise errors; it will just silently fail: const o3 = Object.freeze({}); o3.name = 'css'; console.log(o3.name); // undefined

Identifier Lookup

When an identifier is referenced for reading or writing, Javascript need to determine what identifier it represents. The search starts at the front of the scope chain, looking for an identifier with the given name. If it finds that identifier name in the local context, then the search stops and the variable is set; if the search doesn't find the variable name, it continues along the scope chain. This process continues until the search reaches the global context's variable object. If the identifier isn't found there, it hasn't been declared. Consider the following example: var color = 'blue'; function getColor() { return color; } console.log(getColor()); // 'blue' When the function getColor() is called in this example, the variable color is referenced. At that point, a two-step search begins. First getColor()'s variable object is searched for an identifier named color. When it isn't found, the search goes to the next variable object, the global context, and then searches for an identifier named color. Because color is defined in that variable object, the search ends. Referencing local variables automatically stops the search from going into another variable object. The identifiers in a parent context cannot be referenced if an identifier in the local context has the same name, as in this example: var color = 'blue'; function getColor() { let color = 'red'; return color; } console.log(getColor()); // 'red' Using block scoped declarations does not change the search process, but it can add extra levels to the lexical hierarchy: var color = 'blue'; function getColor() { let color = 'red'; { let color = 'green'; return color; } } console.log(getColor()); // 'green' In this modified code, a local variable named color is declared inside the getColor() function. When the function is called, the variable is declared. When the second line of the function is executed, it knows that a variable named color must be used. The search begins in the local context, where it finds a variable named color with a value of 'green'. Because the variable was found, the search stops and the local variable is used, meaning that the function returns 'green'.

String Type

The String data type represents a sequence of zero or more 16-bit Unicode characters. Strings can be delineated by either double quotes ", single quotes ', or backticks `, so all of the following are legal: let firstName = "css"; let lastName = 'html'; let lastName = `this is a test from demo2s.com`; A string beginning with a certain character must end with the same character. For example, the following will cause a syntax error: let firstName = 'CSS"; // syntax error - quotes must match Here are some examples const a = 'a'; console.log(a); const b = "b"; console.log(b); const c = `c`; console.log(c); Output:

Operation

To determine the length of a string-the number of 16-bit values it contains-use the length property of the string: s.length JavaScript provides a rich API for working with strings: let s = "Hello, world"; // Start with some text. Obtaining portions of a string s.substring(1,4) // => "ell": the 2nd, 3rd, and 4th characters. s.slice(1,4) // => "ell": same thing s.slice(-3) // => "rld": last 3 characters s.split(", ") // => ["Hello", "world"]: split at delimiter string Searching a string s.indexOf("l") // => 2: position of first letter l s.indexOf("l", 3) // => 3: position of first "l" at or after 3 s.indexOf("zz") // => -1: s does not include the substring "zz" s.lastIndexOf("l") // => 10: position of last letter l Boolean searching functions s.startsWith("Hell") // => true: the string starts with these s.endsWith("!") // => false: s does not end with that s.includes("or") // => true: s includes substring "or" Creating modified versions of a string s.replace("llo", "ya") // => "Heya, world" s.toLowerCase() // => "hello, world" s.toUpperCase() // => "HELLO, WORLD" s.normalize() // Unicode NFC normalization: ES6 s.normalize("NFD") // NFD normalization. Inspecting individual (16-bit) characters of a string s.charAt(0) // => "H": the first character s.charAt(s.length-1) // => "d": the last character s.charCodeAt(0) // => 72: 16-bit number at the specified position s.codePointAt(0) // => 72: ES6, works for codepoints > 16 bits String padding functions "x".padStart(3) // => " x": add spaces on the left to a length of 3 "x".padEnd(3) // => "x ": add spaces on the right to a length of 3 "x".padStart(3, "*") // => "**x": add stars on the left to a length of 3 "x".padEnd(3, "-") // => "x--": add dashes on the right to a length of 3 Space trimming functions. trim() is ES5; others ES2019 " test ".trim() // => "test": remove spaces at start and end " test ".trimStart() // => "test ": remove spaces on left. Also trimLeft " test ".trimEnd() // => " test": remove spaces at right. Also trimRight Other string methods s.concat("!") // => "Hello, world!": just use + operator instead "<>".repeat(5) // => "<><><><><>": concatenate n copies. ES6 Javascript strings are immutable. Methods like replace() and toUpperCase() return new strings: they do not modify the string on which they are invoked. Strings can also be treated like read-only arrays, and you can access individual characters (16-bit values) from a string using square brackets instead of the charAt() method: let s = "hello, world"; s[0] // => "h" s[s.length-1] // => "d"

String Literals

To include a string in a JavaScript program, simply enclose the characters of the string within a matched pair of single or double quotes or backticks ( ' ' or " " or ` `). Double-quote characters and backticks may be contained within strings delimited by single-quote characters, and similarly for strings delimited by double quotes and backticks. Here are examples of string literals: "" // The empty string: it has zero characters 'testing' "3.14" 'name="myform"' //mix "Wouldn't you prefer paper book?" `"She said 'hi'", he said.` Strings delimited with backticks are a feature of ES6, and allow JavaScript expressions to be embedded within the string literal.

Multiline

You can break a string literal across multiple lines by ending each line but the last with a backslash (\). Neither the backslash nor the line terminator that follow it are part of the string literal. If you need to include a newline character in a single-quoted or double-quoted string literal, use the character sequence \n. The ES6 backtick syntax allows strings to be broken across multiple lines, and in this case, the line terminators are part of the string literal: A string representing 2 lines written on one line: A one-line string written on 3 lines: "one\ long\ line" A two-line string written on two lines: `the newline character at the end of this line is included literally in this string` Note that when you use single quotes to delimit your strings, you must be careful with English contractions and possessives, such as can't. Since the apostrophe is the same as the single-quote character, you must use the backslash character (\) to "escape" any apostrophes that appear in single-quoted strings. In client-side JavaScript programming, JavaScript code may contain strings of HTML code, and HTML code may contain strings of JavaScript code. Like JavaScript, HTML uses either single or double quotes to delimit its strings. Thus, when combining Java Script and HTML, it is a good idea to use one style of quotes for JavaScript and the other style for HTML. In the following example, the string "Thank you" is single- quoted within a JavaScript expression, which is then double-quoted within an HTML event-handler attribute: <button onclick="alert('Thank you')">Click Me</button>

String Character Escape

The String data type includes several character literals to represent nonprintable useful characters, as listed in the following table:
LITERAL MEANING
\n New line
\t Tab
\b Backspace
\r Carriage return
\f Form feed
\\ Backslash (\)
\' Single quote '-used when the string is delineated by single quotes.
Example: 'He said, \'hi.\''.
\" Double quote (")-used when the string is delineated by double quotes.
Example: "He said, \"hi.\"".
\` Backtick (`)-used when the string is delineated by backticks.
Example: `He said, \`hi.\``.
\xnn A character represented by hexadecimal code nn (where n is a hexadecimal digit 0-F).
Example: \x41 is equivalent to "A".
\unnnn A Unicode character represented by the hexadecimal code nnnn (where n is a hexadecimal digit 0-F).
Example: \u03a3 is equivalent to the Greek character S.
These character literals can be included anywhere with a string and will be interpreted as if they were a single character, as shown here: let text = "This is the letter sigma: \u03a3."; The entire escape sequence represents a single character, so it is counted as such. The length of any string can be returned by using the length property, as follows: console.log("asdf".length); //4 This property returns the number of 16-bit characters in the string. If a string contains double-byte characters, the length property may not accurately return the number of characters in the string.

immutable String

Strings are immutable in ECMAScript, and once they are created, their values cannot change. To change the string held by a variable, the original string must be destroyed and the variable filled with another string containing a new value, like this: let lang = "Java"; lang = lang + "Script"; Here, the variable lang is defined to contain the string "Java". On the next line, lang is redefined to combine "Java" with "Script", making its value "JavaScript". The last step in the process is to destroy the original string "Java" and the string "Script", because neither is necessary anymore. All of this happens behind the scenes.

Converting value to a String using toString() method

There are two ways to convert a value into a string. The first is to use the toString() method that almost every value has. This method's job is to return the string equivalent of the value. Consider this example: let age = 11; let ageAsString = age.toString(); // the string "11" let found = true; let foundAsString = found.toString(); // the string "true" The toString() method is available on values that are numbers, Booleans, objects, and strings. If a value is null or undefined, this method is not available. In most cases, toString() doesn't have any arguments. However, when used on a number value, toString() actually accepts a single argument: the radix in which to output the number. By default, toString() always returns a string that represents the number as a decimal, but by passing in a radix, toString() can output the value in binary, octal, hexadecimal, or any other valid base, as in this example: let num = 10; console.log(num.toString()); // "10" console.log(num.toString(2)); // "1010" console.log(num.toString(8)); // "12" console.log(num.toString(10)); // "10" console.log(num.toString(16)); // "a" This example shows how the output of toString() can change for numbers when providing a radix. The value 10 can be output into any number of numeric formats. The default is the same as providing a radix of 10.

Converting value to a String using String() method

If you're not sure that a value isn't null or undefined, you can use the String() casting function, which always returns a string regardless of the value type. The String() function follows these rules: If the value has a toString() method, it is called and the result is returned. If the value is null, "null" is returned. If the value is undefined, "undefined" is returned. Consider the following: let value1 = 10; let value2 = true; let value3 = null; let value4; console.log(String(value1)); // "10" console.log(String(value2)); // "true" console.log(String(value3)); // "null" console.log(String(value4)); // "undefined" Here, four values are converted into strings: a number, a Boolean, null, and undefined. The result for the number and the Boolean are the same as if toString() were called. Because toString() isn't available on "null" and "undefined", the String() method simply returns literal text for those values. You can also convert a value to a string by adding an empty string ("") to that value using the plus operator.

String Template Literals

ECMAScript can define strings using template literals. Unlike single and double quoted, template literals respect new line characters, and can be defined spanning multiple lines: let myMultiLineString = 'first line\nsecond line'; console.log(myMultiLineString); // first line // second line let myMultiLineTemplateLiteral = `first line second line`; console.log(myMultiLineTemplateLiteral); // first line // second line console.log(myMultiLineString === myMultiLineTemplateLiteral); // true Output: The template literals are useful when defining templates, such as HTML: let pageHTML = ` <div> <a href="#"> <span>Javascript</span> </a> </div>`; Because template literals will exactly match the whitespace inside the backticks, special care will need to be applied when defining them. A correctly formatted template string may appear to have improper indentation: This template literal has 25 spaces following the line return character let myTemplateLiteral = `A B`; console.log(myTemplateLiteral.length); Output: This template literal begins with a line return character let secondTemplateLiteral = ` A B`; console.log(secondTemplateLiteral[0] === '\n'); // true This template literal has no unexpected whitespace characters let thirdTemplateLiteral = `A B`; console.log(thirdTemplateLiteral[0]); Output:

String Template Interpolation

Javascript template literals supports for interpolation. We can insert values at one or more places inside a String template. Javascript String Templates are special JavaScript syntactical expressions that evaluate into strings. Template literals are evaluated immediately when they are defined and converted into a string instance, and any interpolated variables will be drawn from its immediate scope. This can be accomplished using a JavaScript expression inside ${}: let name = "Bill"; let greeting = `Hello ${ name }.`; // greeting == "Hello Bill." let value = 5; let exponent = '2'; let interpolatedTemplateLiteral = `${ value } to the ${ exponent } power is ${ value * value }`; console.log(interpolatedTemplateLiteral); // 5 to the 2 power is 25 The value being interpolated will eventually be coerced into a string using toString(), but any JavaScript expression can safely be interpolated. Nesting template strings is safe with no escaping required: console.log(`Hello, ${ `World` }!`); // Hello, World! toString() is invoked to coerce expression result into string: let foo = { toString: () => 'World' }; console.log(`Hello, ${ foo }!`); // Hello, World! Invoking functions and methods inside interpolated expressions is allowed: function capitalize(word) { return `${ word[0].toUpperCase() }${ word.slice(1) }`; } console.log(`${ capitalize('hello') }, ${ capitalize('world') }!`); // Hello, World! Additionally, templates can safely interpolate their previous value: let value = ''; function append() { value = `${value}a` console.log(value); } append(); // a append(); // aa append(); // aaa

String Template Literal Tag Functions

Template literals can define tag functions to define custom interpolation behavior. A tag function is defined as a regular function and is applied to a template literal by being prepended to it. The tag function will be passed the template literal split into its pieces: the first argument is an array of the raw strings, and the remaining arguments are the results of the evaluated expressions. The return value of this function will be the string evaluated from the template literal. let a = 6;/*w w w. d e m o 2 s . c o m */ let b = 9; function simpleTag(strings, aVal, bVal, sumVal) { console.log(strings); console.log(aVal); console.log(bVal); console.log(sumVal); return 'test'; } let untaggedResult = `${ a } + ${ b } = ${ a + b }`; let taggedResult = simpleTag`${ a } + ${ b } = ${ a + b }`; // ["", " + ", " = ", ""] // 6 // 9 // 15 console.log(untaggedResult); // "6 + 9 = 15" console.log(taggedResult); // "test" Because there are a variable number of expression arguments, using the spread operator to combine them into a single collection is usually prudent: let a = 6; let b = 9; function simpleTag(strings, ...expressions) { console.log(strings); for(const expression of expressions) { console.log(expression); } return 'test'; } let taggedResult = simpleTag`${ a } + ${ b } = ${ a + b }`; // ["", " + ", " = ", ""] // 6 // 9 // 15 console.log(taggedResult); // "test" For a template literal with n interpolated values, the number of expression arguments to the tag function will always be n, and the number of string pieces in the first argument will always be exactly n + 1. If you wished to zip the strings and the evaluated expressions together into the default returned string, you could do so as follows: let a = 6; let b = 9; function zipTag(strings, ...expressions) { return strings[0] + expressions.map((e, i) => `${e}${strings[i + 1]}`) .join(''); } let untaggedResult = `${ a } + ${ b } = ${ a + b }`; let taggedResult = zipTag`${ a } + ${ b } = ${ a + b }`; console.log(untaggedResult); // "6 + 9 = 15" console.log(taggedResult); // "6 + 9 = 15"

Get Raw Strings from String template literals

We can get the raw template literal contents without being converted into actual character representations, such as a new line or Unicode character. This can be done by using the String.raw tag function. Unicode demo // \u00A9 is the copyright symbol console.log(`\u00A9`); console.log(String.raw`\u00A9`); // \u00A9 Newline demo console.log(`first line\nsecond line`); // first line // second line console.log(String.raw`first line\nsecond line`); // "first line\nsecond line" This does not work for actual newline characters: they do not undergo conversion from their plaintext escaped equivalents console.log(`first line second line`); // first line // second line console.log(String.raw`first line second line`); // first line // second line The raw values are available as a property on each element in the string piece collection inside the tag function: function printRaw(strings) { console.log('Actual characters:'); for (const string of strings) { console.log(string); } console.log('Escaped characters;'); for (const rawString of strings.raw) { console.log(rawString); } } printRaw`a\nb${ 'and' }\n`; Output:

String Reference Type

The String type is the object representation for strings and is created using the String constructor as follows: let stringObject = new String("hi"); The methods of a String object are available on all string primitives. All three of the inherited methods-valueOf(), toLocaleString(), and toString()-return the object's primitive string value. Each instance of String contains a single property, length, which indicates the number of characters in the string. Consider the following example: let stringValue = "hello world"; console.log(stringValue.length); // "11" This example outputs "11", the number of characters in "hello world". Note that even if the string contains a double-byte character, each character is still counted as one. The String type has a large number of methods to aid in the dissection and manipulation of strings in ECMAScript.

String Character

JavaScript strings consist of 16 bit code units. For most characters, each 16 bit code unit will correspond to a single character.

Length

The length property indicates how many 16 bit code units occur inside the string: let message = "abcde"; console.log(message.length); // 5

charAt()

The charAt() returns the character at a given index, specified by an integer argument to the method. This method finds the 16 bit code unit at the specified index and returns the character that corresponds to that code unit: let message = "abcde"; console.log(message.charAt(2)); // "c"

charCodeAt()

You can inspect the character encoding of a given code unit with the charCodeAt() method. This method returns the code unit value at a given index, specified by an integer argument to the method. This method is demonstrated here: let message = "abcde"; // Unicode "Latin small letter C" is U+0063 console.log(message.charCodeAt(2)); // 99 // Decimal 99 === Hexadecimal 63 console.log(99 === 0x63); // true

fromCharCode()

The fromCharCode() method is used for creating characters in a string from their UTF-16 code unit representation. This method accepts any number of numbers and returns their character equivalents concatenated into a string: // Unicode "Latin small letter A" is U+0061 and === 97 // Unicode "Latin small letter B" is U+0062 and === 98 // Unicode "Latin small letter C" is U+0063 and === 99 // Unicode "Latin small letter D" is U+0064 and === 100 // Unicode "Latin small letter E" is U+0065 and === 101 console.log(String.fromCharCode(0x61, 0x62, 0x63, 0x64, 0x65)); // "abcde" console.log(String.fromCharCode(97, 98, 99, 100, 101)); // "abcde" For characters in the range of U+0000 to U+FFFF, length, charAt(), charCodeAt(), and fromCharCode() all behave exactly as you would expect them to. This is because every character is represented by exactly 16 bits, and each of these methods are all operating on 16 bit code units.

String normalize Unicode character

Some Unicode characters can be encoded in more than one way. Sometimes, a character can be represented by either a single BMP character or a surrogate pair. For example, consider the following: // U+00C5: Latin capital letter A with ring above console.log(String.fromCharCode(0x00C5)); // U+212B: Angstrom sign console.log(String.fromCharCode(0x212B)); Comparison operators do not care about the visual appearance of characters, and so these three will be considered distinct: let a1 = String.fromCharCode(0x00C5), a2 = String.fromCharCode(0x212B), console.log(a1, a2); console.log(a1 === a2); // false

Normalization

We can normalize Unicode by four normalization forms. The unicode character can be normalized into a consistent format irrespective of their character code derivation. These four normalization forms can be applied to a string using the normalize() method. Normalization Form D (NFD), Normalization Form C (NFC), Normalization Form KD (NFKD), and Normalization Form KC (NFKC) The normalize() method should be provided with a string identifier to specify which normalization form to apply: NFD, NFC, NFKD, or NFKC. It is possible to determine if a string is already normalized by checking it against the return value of normalize(): let a1 = String.fromCharCode(0x00C5), a2 = String.fromCharCode(0x212B), // U+00C5 is the NFC/NFKC normalized form of 0+212B console.log(a1 === a1.normalize("NFD")); // false console.log(a1 === a1.normalize("NFC")); // true console.log(a1 === a1.normalize("NFKD")); // false console.log(a1 === a1.normalize("NFKC")); // true // U+212B is non-normalized console.log(a2 === a2.normalize("NFD")); // false console.log(a2 === a2.normalize("NFC")); // false console.log(a2 === a2.normalize("NFKD")); // false console.log(a2 === a2.normalize("NFKC")); // false Selecting a normal form will allow for the comparison operator to behave as expected between identical characters: let a1 = String.fromCharCode(0x00C5), a2 = String.fromCharCode(0x212B), console.log(a1.normalize("NFD") === a2.normalize("NFD")); // true

String concatenation

Several methods manipulate the values of strings.

concat()

The first of these methods is concat(), which is used to concatenate one or more strings to another, returning the concatenated string as the result. Consider the following example: let stringValue = "hello "; let result = stringValue.concat("world"); console.log(result); // "hello world" console.log(stringValue); // "hello" The result of calling the concat() method on stringValue in this example is "hello world"- the value of stringValue remains unchanged. The concat() method accepts any number of arguments, so it can create a string from any number of other strings, as shown here: let stringValue = "hello "; let result = stringValue.concat("world", "!"); console.log(result); // "hello world!" console.log(stringValue); // "hello" This modified example concatenates "world" and "!" to the end of "hello". The addition operator (+) is used more often than concat() method.

Get String sub string using slice(), substr(), and substring()

ECMAScript provides three methods for creating string values from a substring: slice(), substr(), and substring(). All three methods return a substring of the string they act on, and all accept either one or two arguments. The first argument is the position where capture of the substring begins; the second argument, if used, indicates where the operation should stop. For slice() and substring(), this second argument is the position before which capture is stopped. All characters up to this point are included except the character at that point. For substr(), the second argument is the number of characters to return. If the second argument is omitted in any case, it is assumed that the ending position is the length of the string. slice(), substr(), and substring() do not alter the value of the string itself-they simply return a primitive string value as the result, leaving the original unchanged. Consider this example: let stringValue = "hello world"; console.log(stringValue.slice(3)); // "lo world" console.log(stringValue.substring(3)); // "lo world" console.log(stringValue.substr(3)); // "lo world" console.log(stringValue.slice(3, 7)); // "lo w" console.log(stringValue.substring(3,7)); // "lo w" console.log(stringValue.substr(3, 7)); // "lo worl" In this example, slice(), substr(), and substring() are used in the same manner and, in most cases, return the same value. When given just one argument, 3, all three methods return "lo world" because the second "l" in "hello" is in position 3. When given two arguments, 3 and 7, slice() and substring() return "lo w", while substr() returns "lo worl" because the second argument specifies the number of characters to return.

Negative index

There are different behaviors for these methods when an argument is a negative number. For the slice() method, a negative argument is treated as the length of the string plus the negative argument. For the substr() method, a negative first argument is treated as the length of the string plus the number, whereas a negative second number is converted to 0. For the substring() method, all negative numbers are converted to 0. Consider this example: let stringValue = "hello world"; console.log(stringValue.slice(-3)); // "rld" console.log(stringValue.substring(-3)); // "hello world" console.log(stringValue.substr(-3)); // "rld" console.log(stringValue.slice(3, -4)); // "lo w" console.log(stringValue.substring(3, -4)); // "hel" console.log(stringValue.substr(3, -4)); // "" (empty string) When slice() and substr() are called with a single negative argument, they act the same. This occurs because -3 is translated into 7, which is the length plus the argument, effectively making the calls slice(7) and substr(7). The substring() method returns the entire string because -3 is translated to 0. When the second argument is negative, the three methods act differently from one another. The slice() method translates the second argument to 7, making the call equivalent to slice(3, 7) and so returning "lo w". For the substring() method, the second argument gets translated to 0, making the call equivalent to substring(3, 0), which is actually equivalent to substring(0,3) because this method expects that the smaller number is the starting position and the larger one is the ending position. For the substr() method, the second argument is also converted to 0, which means there should be zero characters in the returned string, leading to the return value of an empty string.

String Search Location Methods

There are two methods for locating substrings within another string: indexOf() and lastIndexOf(). Both methods search a string for a given substring and return the position or -1 if the substring isn't found. The indexOf() method begins looking for the substring at the beginning of the string, whereas the lastIndexOf() method begins looking from the end of the string. Consider this example: let stringValue = "hello world"; console.log(stringValue.indexOf("o")); // 4 console.log(stringValue.lastIndexOf("o")); // 7 Here, the first occurrence of the string "o" is at position 4, which is the "o" in "hello". The last occurrence of the string "o" is in the word "world", at position 7. If there is only one occurrence of "o" in the string, then indexOf() and lastIndexOf() return the same position. Each method accepts an optional second argument that indicates the position to start searching from within the string. The indexOf() method will start searching from that position and go toward the end of the string, ignoring everything before the start position. The last IndexOf() starts searching from the given position and continues searching toward the beginning of the string, ignoring everything between the given position and the end of the string. Here's an example: let stringValue = "hello world"; console.log(stringValue.indexOf("o", 6)); // 7 console.log(stringValue.lastIndexOf("o", 6)); // 4 When the second argument of 6 is passed into each method, the results are the opposite from the previous example. indexOf() returns 7 because it starts searching the string from position 6 (the letter "w") and continues to position 7, where "o" is found. The lastIndexOf() method returns 4 because the search starts from position 6 and continues back toward the beginning of the string, where it encounters the "o" in "hello". Using this second argument allows you to locate all instances of a substring by looping callings to indexOf() or lastIndexOf(), as in the following example: let stringValue = "Cate Kate Jane Jason Joe"; let positions = new Array(); let pos = stringValue.indexOf("e"); while(pos > -1) { positions.push(pos); pos = stringValue.indexOf("e", pos + 1); } console.log(positions); Output: This example works through a string by constantly increasing the position at which indexOf() should begin. It begins by getting the initial position of "e" in the string and then enters a loop that continually passes in the last position plus one to indexOf(), ensuring that the search continues after the last substring instance. Each position is stored in the positions array so the data can be used later.

String Inclusion Contains Methods

ECMAScript 6 added three additional methods for determining if a string is included inside another string: startsWith(), endsWith(), and includes(). All methods search a string for a given substring and return a boolean indicating whether it is not included. startsWith() checks for a match beginning at index 0. endsWith() checks for a match beginning at index of (string.length - substring.length). includes() checks the entire string. let message = "foobarbaz"; console.log(message.startsWith("foo")); // true console.log(message.startsWith("bar")); // false console.log(message.endsWith("baz")); // true console.log(message.endsWith("bar")); // false console.log(message.includes("bar")); // true console.log(message.includes("qux")); // false The startsWith() and includes() methods accept an optional second argument that indicates the position to start searching from within the string. The methods will start searching from that position and go toward the end of the string, ignoring everything before the start position. Here's an example: let message = "foobarbaz"; console.log(message.startsWith("foo")); // true console.log(message.startsWith("foo", 1)); // false console.log(message.includes("bar")); // true console.log(message.includes("bar", 4)); // false The endsWith() method accepts an optional second argument that indicates the position that should be treated as the end of the string. If this value is not provided, the length of the string is used by default. When a second argument is provided, the method will treat the string as if it only has that many characters: let message = "foobarbaz"; console.log(message.endsWith("bar")); // false console.log(message.endsWith("bar", 6)); // true

Use String trim() Method to remove leading and trailing white space

ECMAScript features a trim() method on all strings. The trim() method creates a copy of the string, removes all leading and trailing white space, and then returns the result. For example: let stringValue = " hello world "; let trimmedStringValue = stringValue.trim(); console.log(stringValue); // " hello world " console.log(trimmedStringValue); // "hello world" Since trim() returns a copy of a string, the original string remains intact with leading and trailing white space in place. The trimLeft() and trimRight() methods remove white space only from the beginning or end of the string, respectively.

Create a String via repeat() Method

ECMAScript features a repeat() method on all strings. The repeat() method accepts a single integer argument count, copies the string count times, and concatenates all the copies. let stringValue = "hi "; console.log(stringValue.repeat(6) + "hello"); Output:

Pad a String via padStart() and padEnd() Methods

The padStart() and padEnd() methods will copy a string and, if the length of the string is less than the specified length, add padding to either side of a string to extend it to a certain length. The first argument is the desired length, and the second is the optional string to add as a pad. If not provided, the U+0020 'space' character will be used. let stringValue = "foo"; console.log(stringValue.padStart(6)); // " foo" console.log(stringValue.padStart(9, ".")); // "......foo" console.log(stringValue.padEnd(6)); // "foo " console.log(stringValue.padEnd(9, ".")); // "foo......" The optional argument is not limited to a single character. If provided a multiple-character string, the method will use the concatenated padding and truncate it to the exact length. Additionally, if the length is less than or equal to the string length, the operation is effectively a no-op. let stringValue = "foo"; console.log(stringValue.padStart(8, "bar")); // "barbafoo" console.log(stringValue.padStart(2)); // "foo" console.log(stringValue.padEnd(8, "bar")); // "foobarba" console.log(stringValue.padEnd(2)); // "foo"

String Iterators

The string prototype exposes an @@iterator method on each string, which allows for iteration through individual characters. Manual use of the iterator works as follows: let message = "abc"; let stringIterator = message[Symbol.iterator](); console.log(stringIterator.next()); // {value: "a", done: false} console.log(stringIterator.next()); // {value: "b", done: false} console.log(stringIterator.next()); // {value: "c", done: false} console.log(stringIterator.next()); // {value: undefined, done: true} When used in a for of loop, the loop will use this iterator to visit each character in order: for (const c of "abcde") { console.log(c); } Output:

String Destructuring

The string iterator allows for interoperability with the destructuring operator. This allows you to easily split a string by its characters: let message = "abcde"; console.log([...message]); Output:

Use String Case Methods to change string case

Four methods perform case conversion: toLowerCase(), toLocaleLowerCase(), toUpperCase(), and toLocaleUpperCase(). The toLowerCase() and toUpperCase() methods are the original methods. The toLocaleLowerCase() and toLocaleUpperCase() methods are intended to be implemented based on a particular locale. In many locales, the locale-specific methods are identical to the generic ones; however, a few languages (such as Turkish) apply special rules to Unicode case conversion, and this necessitates using the locale-specific methods for proper conversion. Here are some examples: let stringValue = "hello world"; console.log(stringValue.toLocaleUpperCase()); // "HELLO WORLD" console.log(stringValue.toUpperCase()); // "HELLO WORLD" console.log(stringValue.toLocaleLowerCase()); // "hello world" console.log(stringValue.toLowerCase()); // "hello world" This code outputs "HELLO WORLD" for both toLocaleUpperCase() and toUpperCase(), just as "hello world" is output for both toLocaleLowerCase() and toLowerCase().

String Pattern-Matching Methods

The String type has several methods designed to pattern-match within the string.

match()

String match() is the same as calling a RegExp object's exec() method. The match() method accepts a single argument, which is either a regular-expression string or a RegExp object. Consider this example: let text = "cat, bat, sat, fat"; let pattern = /.at/; // same as pattern.exec(text) let matches = text.match(pattern); console.log(matches.index); // 0 console.log(matches[0]); // "cat" console.log(pattern.lastIndex); // 0 The array returned from match() is the same array that is returned when the RegExp object's exec() method is called with the string as an argument: the first item is the string that matches the entire pattern, and each other item (if applicable) represents capturing groups in the expression.

search()

String search() finds patterns. String search() method accepts a regular expression specified by either a string or a RegExp object as its parameter. The search() method returns the index of the first pattern occurrence in the string or -1 if it's not found. search() always begins looking for the pattern at the beginning of the string. Consider this example: let text = "cat, bat, sat, fat"; let pos = text.search(/at/); console.log(pos); // 1 Here, search(/at/) returns 1, which is the first position of "at" in the string.

Use replace() method to replace sub string

To replace substrings, ECMAScript provides the replace() method. This method accepts two arguments. The first argument can be a RegExp object or a string which is not converted to a regular expression, and the second argument can be a string or a function. If the first argument is a string, then only the first occurrence of the substring will be replaced. The only way to replace all instances of a substring is to provide a regular expression with the global flag specified, as in this example: let text = "cat, bat, sat, fat"; let result = text.replace("at", "ond"); console.log(result); // "cond, bat, sat, fat" result = text.replace(/at/g, "ond"); console.log(result); // "cond, bond, sond, fond" In this example, the string "at" is first passed into replace() with a replacement text of "ond". The result of the operation is that "cat" is changed to "cond", but the rest of the string remains intact. By changing the first argument to a regular expression with the global flag set, each instance of "at" is replaced with "ond". When the second argument is a string, there are several special character sequences that can be used to insert values from the regular-expression operations. ECMA-262 specifies the following table of values.
Sequence Replacement Text
$$ $
$& The substring matching the entire pattern. Same as RegExp.lastMatch.
$' The part of the string occurring before the matched substring.
Same as RegExp.rightContext.
$` The part of the string occurring after the matched substring.
Same as RegExp.leftContext.
$n The nth capture, where n is a value 0-9.
For instance, $1 is the first capture, $2 is the second, and so on.
If there is no capture then the empty string is used.
$nn The nnth capture, where nn is a value 01-99.
For instance, $01 is the first capture, $02 is the second, and so on.
If there is no capture then the empty string is used.
Using these special sequences allows replacement using information about the last match, such as in this example: let text = "cat, bat, sat, fat"; result = text.replace(/(.at)/g, "word ($1)"); console.log(result); // word (cat), word (bat), word (sat), word (fat) Here, each word ending with "at" is replaced with "word" followed in parentheses by what it replaces by using the $1 sequence. The second argument of replace() may also be a function. When there is a single match, the function gets passed three arguments: the string match, the position of the match within the string, and the whole string. When there are multiple capturing groups, each matched string is passed in as an argument, with the last two arguments being the position of the pattern match in the string and the original string. The function should return a string indicating what the match should be replaced with. Using a function as the second argument allows more granular control over replacement text, as in this example: function htmlEscape(text) { return text.replace(/[<>"&]/g, function(match, pos, originalText) { switch(match) { case "<": return "&lt;"; case ">": return "&gt;"; case "&": return "&amp;"; case "\"": return "&quot;"; } }); } console.log(htmlEscape("<p class=\"greeting\">Hello world!</p>")); Output: Here, the function htmlEscape() is defined to escape four characters for insertion into HTML: the less-than, greater-than, ampersand, and double-quote characters all must be escaped. We use a regular expression to look for those characters and then define a function that returns the specific HTML entities for each matched character.

Use split() method to split string

String split() separates the string into an array of substrings based on a separator. The separator may be a string or a RegExp object. The string is not converted to a regular expression for this method. An optional second argument, the array limit, ensures that the returned array will be no larger than a certain size. Consider this example: let sText = "A,B,C,D,E"; let s1 = sText.split(","); let s2 = sText.split(",", 2); let s3 = sText.split(/[^\,]+/); console.log(s1); console.log(s2); console.log(s3); Output: In this example, the string sText is a comma-separated string of letters. The call to split(",") retrieves an array of those letters, splitting the string on the comma character. To truncate the results to only two items, a second argument of 2 is specified. Last, using a regular expression, it's possible to get an array of the comma characters.

Compare String with localeCompare() Method

String localeCompare() compares one string to another and returns one of three values as follows: If the string should come alphabetically before the string argument, a negative number is returned. If the string is equal to the string argument, 0 is returned. If the string should come alphabetically after the string argument, a positive number is returned. Here's an example: let stringValue = "y"; console.log(stringValue.localeCompare("b")); // 1 console.log(stringValue.localeCompare("y")); // 0 console.log(stringValue.localeCompare("z")); // -1 In this code, the string "y" is compared to three different values: "b", "y", and "z". Because "b" comes alphabetically before "y", localeCompare() returns 1; "y" is equal to "y", so localeCompare() returns 0 for that line; and "z" comes after "y", so localeCompare() returns -1 for that line. The returned values are implementation-specific, it is best to use localeCompare() as shown in this example: function determineOrder(value) { let stringValue = "y"; let result = stringValue.localeCompare(value); if (result < 0) { console.log(`The string 'y' comes before the string '${value}'.`); } else if (result > 0) { console.log(`The string 'y' comes after the string '${value}'.`); } else { console.log(`The string 'y' is equal to the string '${value}'.`); } } determineOrder("b"); determineOrder("y"); determineOrder("z"); Output: localeCompare() is depended on an implementation's locale (country and language). In the United States, where English is the standard language for ECMAScript implementations, localeCompare() is case-sensitive, determining that uppercase letters come alphabetically after lowercase letters. This may not be the case in other locales.

String HTML Methods

The web browser vendors recognized a need early on to format HTML dynamically using JavaScript. As a result, they extended the specification to include several methods specifically designed to aid in common HTML formatting tasks. The following table enumerates the HTML methods. Typically these methods aren't used, because they tend to create non-semantic markup.
Method Output
anchor(name) <a name="name ">string</a>
big() <big>string</big>
bold() <b>string</b>
fixed() <tt>string</tt>
fontcolor(color) <font color="color">string</font>
fontsize(size) <font size="size">string</font>
italics() <i>string</i>
link(url) <a href="url">string</a>
small() <small>string</small>
strike() <strike>string</strike>
sub() <sub>string</sub>
sup() <sup>string</sup>

String search()

The search() method executes a search for a regular expression.

Syntax

str.search(regexp)

Parameters

Item Description
regexp A regular expression object.
If a non-RegExp object regexp is passed, it is implicitly converted to a RegExp with new RegExp(regexp).

Return value

The index of the first match between the regular expression and the given string, or -1 if no match was found. The following example searches a string with two different regex objects to show a successful search (positive value) vs. an unsuccessful search (-1) let str = "hey JudE"; let re = /[A-Z]/g; let reDot = /[.]/g; console.log(str.search(re)); // returns 4, which is the index of the first capital letter "J" console.log(str.search(reDot)); // returns -1 cannot find '.' dot punctuation Result

String slice()

The slice() method extracts a sub string and returns it as a new string, without modifying the original string.

Syntax

str.slice(begin_Index[, end_Index])

Parameters

Item Description
begin_Index The zero-based index at which to begin extraction.
end_Index Optional
The zero-based index before which to end extraction.
The character at this index will not be included.
begin_Index possible values: If negative, it is treated as str.length + begin_Index. For example, if begin_Index is -3, it is treated as str.length - 3.) If begin_Index is not a number after Number(begin_Index), it is treated as 0. If begin_Index is greater than or equal to str.length, an empty string is returned. end_Index possible values: If end_Index is omitted or undefined, or greater than str.length, slice() extracts to the end of the string. If negative, it is treated as str.length + end_Index. For example, if end_Index is -3, it is treated as str.length - 3. If it is not undefined and not a number after Number(end_Index), an empty string is returned. If end_Index is specified and start_Index is negative, end_Index should be negative, otherwise an empty string is returned. For example, slice(-3, 0) returns "". If end_Index is specified, and start_Index and end_Index are both positive or negative, end_Index should be greater than start_Index, otherwise an empty string is returned. For example, slice(-1, -3) or slice(3, 1) returns "".

Return value

A new string containing the extracted section of the string. The following example uses slice() to create a new string. let str1 = 'This is a test from us.', str2 = str1.slice(1, 8), str3 = str1.slice(4, -2), str4 = str1.slice(12), str5 = str1.slice(30); console.log(str2); console.log(str3); console.log(str4); console.log(str5); Result Using slice() with negative indexes The following example uses slice() with negative indexes. let str = 'This is a test from us.'; a = str.slice(-3); console.log(a); a = str.slice(-3, -1); console.log(a); a = str.slice(0, -1); console.log(a); Result This example counts backwards from the end of the string by 11 to find the start index and forwards from the start of the string by 16 to find the end index. let str = 'This is a test from us.'; console.log(str.slice(-11, 16)); Result Here it counts forwards from the start by 11 to find the start index and backwards from the end by 7 to find the end index. let str = 'This is a test from us.'; console.log(str.slice(11, -7)); Result These arguments count backwards from the end by 5 to find the start index and backwards from the end by 1 to find the end index. let str = 'This is a test from us.'; console.log(str.slice(-5, -1)); Result

String small()

Deprecated The small() method creates a <small> HTML element to display a string in a small font. The small() method embeds a string in a <small> tag: "<small>str</small>".

Syntax

str.small()

Return value

A string containing a <small> HTML element. 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</fontsize> Result With the element.style object you can get the element's style attribute and set it: document.getElementById('yourElemId').style.fontSize = '0.7em';

String split()

The split() method divides a String into an array of substrings by a separator.

Syntax

str.split([separator[, limit]])
Item Description
separator Optional
The separator can be a simple string or it can be a regular expression.
limit Optional
A non-negative integer specifying a limit on the number of substrings to be included in the array.
If limit is 0, [] is returned.

Return value

An Array of strings, split at each point where the separator occurs in the given string. If the string and separator are both empty strings, an empty array is returned. const myString = '' const splits = myString.split() console.log(splits) Result The following example defines a function that splits a string into an array of strings using separator. After splitting the string, the function logs messages indicating the original string, the separator used, the number of elements in the array, and the individual array elements. function splitString(stringToSplit, separator) { const arrayOfStrings = stringToSplit.split(separator) console.log('The original string is: ', stringToSplit) console.log('The separator is: ', separator) console.log('The array has ', arrayOfStrings.length, ' elements: ', arrayOfStrings.join(' / ')) } const tempestString = 'This is a test from demo2s.com.' const monthString = 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec' const space = ' ' const comma = ',' splitString(tempestString, space) splitString(tempestString) splitString(monthString, comma) Result In the following example, split() looks for zero or more spaces, followed by a semicolon, followed by zero or more spaces and, when found, removes the spaces and the semicolon from the string. const names = 'CSS HTML;HTML Javascript; Javascript SQL; SQL Database ;Database ABC ' console.log(names) const re = /\s*(?:;|$)\s*/ const nameList = names.split(re) console.log(nameList) Result In the following example, split() looks for spaces in a string and returns the first 3 splits that it finds. const myString = 'Hello World. How are you doing?' const splits = myString.split(' ', 3) console.log(splits) Result Splitting with a RegExp to include parts of the separator in the result If separator is a regular expression that contains capturing parentheses (), matched results are included in the array. const myString = 'Hello 1 word. Sentence number 2.' const splits = myString.split(/(\d)/) console.log(splits) Result Note: \d matches the character class for digits between 0 and 9. Reversing a String using split() const str = 'demo2s.com' const strReverse = str.split('').reverse().join('') console.log(strReverse); Result

String startsWith()

The startsWith() method determines whether a string begins with a specified string, returning true or false. This method is case-sensitive.

Syntax

str.startsWith(search_String[, position])

Parameters

Item Description
search_String The characters to be searched for at the start of this string.
position Optional
The position in this string at which to begin searching for search_String.
Defaults to 0.

Return value

true if the given characters are found at the beginning of the string; otherwise, false. Using startsWith() //startswith let str = 'To be, or not to be, that is the question.' console.log(str.startsWith('To be')) // true console.log(str.startsWith('not to be')) // false console.log(str.startsWith('not to be', 10)) // true Result

String strike()

Deprecated The strike() method creates a <strike> HTML element that causes a string to be displayed as struck-out text. The strike() method embeds a string in a <strike> tag: "<strike>str</strike>".

Syntax

str.strike()

Return value

A string containing a <strike> HTML element.

Using strike()

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> Result

String constructor

The String constructor can create a new String object. When called instead as a function, it performs type conversion to a primitive string.

Syntax

new String(thing) //constructor syntax String(thing) //call as a function
Item Description
thing Anything to be converted to a string.
String constructor and String function String function and String constructor produce different results: let a = typeof String('Hello world'); // string console.log(a); a = typeof new String('Hello world'); // object console.log(a); Result Here, the function produces a string (the primitive type) as promised. However, the constructor produces an instance of the type String, which is an object wrapper. You should not use the String constructor at all.

String sub()

Deprecated The sub() method creates a <sub> HTML element that causes a string to be displayed as subscript. The sub() method embeds a string in a <sub> tag: "<sub>str</sub>".

Syntax

str.sub()

Return value

A string containing a <sub> HTML element. Using sub() and sup() methods The following example uses the sub() and sup() methods to format a string: var superText = 'superscript'; var subText = 'subscript'; console.log('This is what a ' + superText.sup() + ' looks like.'); console.log('This is what a ' + subText.sub() + ' looks like.'); Result

String substr()

The substr() method returns a portion of the string, starting at the specified index and extending for a given number of characters afterwards.

Syntax

str.substr(start[, length])
Item Description
start The index of the first character to include in the returned substring.
length Optional.
The number of characters to extract.
If start is a positive number, the index starts counting at the start of the string. Its value is capped at str.length. If start is a negative number, the index starts counting from the end of the string. Its value is capped at -str.length. If length is omitted, substr() extracts characters to the end of the string. If length is undefined, substr() extracts characters to the end of the string. If length is a negative number, it is treated as 0. For both start and length, NaN is treated as 0.

Return value

A new string containing the specified part of the given string. substr() extracts length characters from a str, counting from the start index. var aString = 'demo2s.com'; console.log(aString.substr(0, 1)); console.log(aString.substr(1, 0)); console.log(aString.substr(-1, 1)); console.log(aString.substr(1, -1)); console.log(aString.substr(-3)); console.log(aString.substr(1)); console.log(aString.substr(-20, 2)); console.log(aString.substr(20, 2)); Result

String substring()

The substring() method returns a string part between the start and end indexes, or to the end of the string.

Syntax

str.substring(index_Start[, index_End])

Parameters

Item Description
index_Start The index of the first character to include in the returned substring.
index_End Optional
The index of the first character to exclude from the returned substring.
substring() extracts characters from index_Start up to but not including index_End. In particular: If index_End is omitted, substring() extracts characters to the end of the string. If index_Start is equal to index_End, substring() returns an empty string. If index_Start is greater than index_End, then the effect of substring() is as if the two arguments were swapped Any argument value that is less than 0 or greater than stringName.length is treated as if it were 0 and stringName.length, respectively. Any argument value that is NaN is treated as if it were 0.

Return value

A new string containing the specified part of the given string. The following example uses substring() to display characters from the string 'demo2s.com': let anyString = 'demo2s.com' console.log(anyString.substring(0, 1)); console.log(anyString.substring(1, 0)); console.log(anyString.substring(0, 6)); console.log(anyString.substring(4)); console.log(anyString.substring(4, 7)); console.log(anyString.substring(7, 4)); console.log(anyString.substring(0, 7)); console.log(anyString.substring(0, 10)); Result Using substring() with length property The following example uses the substring() method and length property to extract the last characters of a particular string. Get the last four characters: let anyString = 'demo2s.com'; let anyString4 = anyString.substring(anyString.length - 4); console.log(anyString4); Result Get the last 5 characters let anyString = 'demo2s.com'; let anyString5 = anyString.substring(anyString.length - 5); console.log(anyString5); Result The difference between substring() and substr() The arguments of substring() represent the starting and ending indexes, while the arguments of substr() represent the starting index and the number of characters to include in the returned string. substr() is considered a legacy feature in ECMAScript. let text = 'demo2s.com'; console.log(text.substring(2,5)); console.log(text.substr(2,3)) Result Differences between substring() and slice() The substring() method swaps its two arguments if index_Start is greater than index_End, meaning that a string is still returned. The slice() method returns an empty string if this is the case. let text = 'demo2s.com'; console.log(text.substring(5, 2)); console.log(text.slice(5, 2)); Result If either or both of the arguments are negative or NaN, the substring() method treats them as if they were 0. let text = 'demo2s.com'; console.log(text.substring(-5, 2)); console.log(text.substring(-5, -2)); Result slice() also treats NaN arguments as 0, but when it is given negative values it counts backwards from the end of the string to find the indexes. let text = 'demo2s.com'; console.log(text.slice(-5, 2)); console.log(text.slice(-5, -2)); Result

String sup()

Deprecated The sup() method creates a <sup> HTML element that causes a string to be displayed as superscript. The sup() method embeds a string in a <sup> tag: "<sup>str</sup>".

Syntax

str.sup()

Return value

A string containing a <sup> HTML element. Using sub() and sup() methods The following example uses the sub() and sup() methods to format a string: var superText = 'superscript'; var subText = 'subscript'; console.log('This is what a ' + superText.sup() + ' looks like.'); console.log('This is what a ' + subText.sub() + ' looks like.'); Result

String toLocaleLowerCase()

The toLocaleLowerCase() method returns the calling string value converted to lower case, according to any locale-specific case mappings.

Syntax

str.toLocaleLowerCase() str.toLocaleLowerCase(locale) str.toLocaleLowerCase([locale, locale, ...])

Parameters

Item Description
locale Optional
The locale parameter indicates the locale to be used to convert to lower case according to any locale-specific case mappings. If multiple locales are given in an Array, the best available locale is used. The default locale is the host environment's current locale.

Return value

A new string representing the calling string converted to lower case, according to any locale-specific case mappings.

Using toLocaleLowerCase()

let a = 'ALPHABET'.toLocaleLowerCase(); // 'alphabet' console.log(a); a = '\u0130'.toLocaleLowerCase('tr') === 'i'; // true console.log(a); a = '\u0130'.toLocaleLowerCase('en-US') === 'i'; // false console.log(a); let locales = ['tr', 'TR', 'tr-TR', 'tr-u-co-search', 'tr-x-turkish']; let b = '\u0130'.toLocaleLowerCase(locales) === 'i'; // true console.log(b); Result

String toLocaleUpperCase()

The toLocaleUpperCase() method returns the calling string value converted to upper case, according to any locale-specific case mappings.

Syntax

str.toLocaleUpperCase() str.toLocaleUpperCase(locale) str.toLocaleUpperCase([locale, locale, ...])

Parameters

Item Description
locale Optional
indicates the locale to be used to convert to upper case.
If multiple locales are given in an Array, the best available locale is used. The default locale is the host environment's current locale.

Return value

A new string representing the calling string converted to upper case, according to any locale-specific case mappings.

Using toLocaleUpperCase()

let a = 'alphabet'.toLocaleUpperCase(); // 'ALPHABET' console.log(a); a = 'Ges'.toLocaleUpperCase(); // 'GES console.log(a); a = 'i\u0307'.toLocaleUpperCase('lt-LT'); // 'I' console.log(a); let locales = ['lt', 'LT', 'lt-LT', 'lt-u-co-phonebk', 'lt-x-lietuva']; a = 'i\u0307'.toLocaleUpperCase(locales); // 'I' console.log(a); Result

String toLowerCase()

The toLowerCase() method returns the calling string value converted to lower case.

Syntax

str.toLowerCase()

Return value

A new string representing the calling string converted to lower case. toLowerCase() does not affect the value of the string str itself. Using toLowerCase() console.log('ALPHABET'.toLowerCase()); // 'alphabet' Result

String toString()

The toString() method returns a string representing the specified object.

Syntax

str.toString()

Return value

A string representing the calling object. Using toString() The following example displays the string value of a String object: var x = new String('Hello world'); console.log(x.toString()); // logs 'Hello world' Result

String toUpperCase()

The toUpperCase() method returns the calling string value converted to uppercase.

Syntax

str.toUpperCase()

Return value

A new string representing the calling string converted to upper case. Basic usage console.log('alphabet'.toUpperCase()); // 'ALPHABET'

String trim()

The trim() method removes whitespace from both ends of a string. Whitespace includes all the whitespace characters (space, tab, no-break space, etc.) and all the line terminator characters (LF, CR, etc.).

Syntax

str.trim()

Return value

A new string representing the str stripped of whitespace from both ends. Using trim() The following example displays the lowercase string 'foo': var orig = ' foo '; console.log(orig.trim()); // 'foo' Result Another example of .trim() removing whitespace from just one side. var orig = 'foo '; console.log(orig.trim()); // 'foo' Result

String trimEnd()

The trimEnd() method removes whitespace from the end of a string. trimRight() is an alias of this method.

Syntax

str.trimEnd(); str.trimRight();

Return value

A new string representing the calling string stripped of whitespace from its (right) end.

Description

The trimEnd() / trimRight() methods return the string stripped of whitespace from its right end. trimEnd() or trimRight() do not affect the value of the string itself. The following example displays the lowercase string ' foo': var str = ' foo '; console.log(str.length); // 8 str = str.trimEnd(); console.log(str.length); // 6 console.log(str); // ' foo' Result

String trimStart()

The trimStart() method removes whitespace from the beginning of a string. trimLeft() is an alias of this method.

Syntax

str.trimStart(); str.trimLeft();

Return value

A new string representing the calling string stripped of whitespace from its beginning (left end). The following example displays the lowercase string 'foo ': var str = ' foo '; console.log(str.length); // 8 str = str.trimStart(); console.log(str.length); // 5 console.log(str); // 'foo ' Result

String valueOf()

The valueOf() method returns the primitive value of a String object.

Syntax

str.valueOf()

Return value

A string representing the primitive value of a given String object. This method is usually called internally by JavaScript.

Examples

Using valueOf()

var x = new String('Hello world'); console.log(x.valueOf()); // Displays 'Hello world' Result

Symbol Type Introduction

ECMAScript Symbols are primitive values, and symbol instances are unique and immutable. A symbol is a unique identifier for object properties. The symbols should be used as unique tokens to identify special properties.

Basic Symbol Use

Symbols are instantiated using the Symbol function. Because it is its own primitive type, the typeof operator will identify a symbol as symbol. let sym = Symbol(); console.log(typeof sym); // symbol When invoking the function, you can provide an optional string that can be used for identifying the symbol instance when debugging. let genericSymbol = Symbol(); console.log(genericSymbol); // Symbol() let fooSymbol = Symbol('foo'); console.log(fooSymbol); // Symbol(foo); Output: The string you provide is totally separate from the symbol's definition or identity: let genericSymbol = Symbol(); let otherGenericSymbol = Symbol(); let fooSymbol = Symbol('foo'); let mySymbol = Symbol('foo'); console.log(genericSymbol == otherGenericSymbol); // false console.log(fooSymbol == mySymbol); // false We can create a new Symbol instance and use it to key a new property on an object. In this way we can guarantee that we will not overwrite an existing object property. The Symbol function cannot be used with the new keyword. This avoids symbol object wrappers, as is possible with Boolean, String, and Number, which support constructor behavior and instantiate a primitive wrapper object: let myBoolean = new Boolean(); console.log(typeof myBoolean); // "object" let myString = new String(); console.log(typeof myString); // "object" let myNumber = new Number(); console.log(typeof myNumber); // "object" let mySymbol = new Symbol(); // TypeError: Symbol is not a constructor To utilize an object wrapper for symbol, you can make use of the Object() function: let mySymbol = Symbol(); let myWrappedSymbol = Object(mySymbol); console.log(typeof myWrappedSymbol); // "object"

Using the Global Symbol Registry

We can create and reuse symbols in a string-keyed global symbol registry. let fooGlobalSymbol = Symbol.for('foo'); console.log(typeof fooGlobalSymbol); // "object" Symbol.for() is an idempotent operation for each string key. The first time it is called with a given string, it will check the global runtime registry, find that no symbol exists, generate a new symbol instance, and add it to the registry. Additional invocations with the same string key will check the global runtime registry, find that a symbol does exist for that string, and return that symbol instance instead. let fooGlobalSymbol = Symbol.for('foo'); // creates new symbol let mySymbol = Symbol.for('foo'); // reuses existing symbol console.log(fooGlobalSymbol === mySymbol); // true Symbols defined in the global registry are totally distinct from symbols created using Symbol(), even if they share a description: let localSymbol = Symbol('foo'); let globalSymbol = Symbol.for('foo'); console.log(localSymbol === globalSymbol); // false The global registry requires string keys, so anything you provide as an argument to Symbol.for() will be converted to a string. Additionally, the key used for the registry will also be used as the symbol description. let emptyGlobalSymbol = Symbol.for(); console.log(emptyGlobalSymbol); // Symbol(undefined) let globalSymbol = Symbol.for('foo'); console.log(globalSymbol); // Symbol(foo) We can check the global registry using Symbol.keyFor(), which accepts a symbol and will return the global string key for that global symbol, or undefined if the symbol is not a global symbol. // Create global symbol let s = Symbol.for('foo'); console.log(Symbol.keyFor(s)); // foo // Create regular symbol let s2 = Symbol('bar'); console.log(Symbol.keyFor(s2)); // undefined Using Symbol.keyFor() with a non-symbol will throw a TypeError: Symbol.keyFor(123); // TypeError: 123 is not a symbol

Using Symbols as Properties

Anywhere you can normally use a string or number property, you can also use a symbol. This includes object literal properties and Object.defineProperty()/Object.defineProperties(). An object literal can only use a symbol as a property inside the computed property syntax. let s1 = Symbol('test'), s2 = Symbol('demo'), s3 = Symbol('baz'), s4 = Symbol('qux'); let o = {// w w w . d e m o 2 s . c o m [s1]: 'test val' }; // Also valid: o[s1] = 'test val'; console.log(o); // {Symbol{test}: test val} Object.defineProperty(o, s2, {value: 'demo val'}); console.log(o); // {Symbol{test}: test val, Symbol(demo): demo val} Object.defineProperties(o, { [s3]: {value: 'baz val'}, [s4]: {value: 'qux val'} }); console.log(o); // {Symbol{test}: test val, Symbol(demo): demo val, // Symbol{baz}: baz val, Symbol(qux): qux val} Object.getOwnPropertyNames() returns an array of regular properties on an object instance. Object.getOwnPropertySymbols() returns an array of symbol properties on an object instance. The return values of these two methods are mutually exclusive. Object.getOwnPropertyDescriptors() will return an object containing both regular and symbol property descriptors. Reflect.ownKeys() will return both types of keys: let s1 = Symbol('test'), s2 = Symbol('demo'); let o = {// w w w .d e m o 2 s. c o m [s1]: 'test val', [s2]: 'demo val', baz: 'baz val', qux: 'qux val' }; console.log(Object.getOwnPropertySymbols(o)); // [Symbol(test), Symbol(demo)] console.log(Object.getOwnPropertyNames(o)); // ["baz", "qux"] console.log(Object.getOwnPropertyDescriptors(o)); // {baz: {...}, qux: {...}, Symbol(test): {...}, Symbol(demo): {...}} console.log(Reflect.ownKeys(o)); // ["baz", "qux", Symbol(test), Symbol(demo)] Symbols can be directly created and used as properties. We can traverse all the object's symbol properties to get the property key: let o = { [Symbol('test')]: 'test val', [Symbol('demo')]: 'demo val' }; console.log(o); // {Symbol(test): "test val", Symbol(demo): "demo val"} let demoSymbol = Object.getOwnPropertySymbols(o) .find((symbol) => symbol.toString().match(/demo/)); console.log(demoSymbol); // Symbol(demo)

Well-Known Symbols

ECMAScript 6 introduced a collection of well-known symbols that would be used throughout the language to expose internal language behaviors for direct access, overriding, or emulating. These well-known symbols exist as string properties on the Symbol factory function. We can redefine well-known symbols to alter the behavior of the native language constructs. For example, the for-of loop will use the Symbol.iterator property, we can provide a custom definition of Symbol.iterator's value in a custom object in order to control how for-of behaves for that object. These well-known symbols are regular string properties on the Symbol global that identify an instance of a symbol. Each well-defined symbol property is non-writeable, non-enumerable, and non-configurable. The well-known symbols are referred by their specification names prefixed with @@. For example, @@iterator refers to Symbol.iterator.

Well Known Symbol Symbol.asyncIterator

Well Known Symbol Symbol.asyncIterator is used as a property for "A method that returns the default AsyncIterator for an object. Called by the semantics of the for-await-of statement". It is used to identify the function that implements the asynchronous iterator API. The for-await-of loop uses this function to perform asynchronous iteration. They will invoke the function keyed by Symbol.asyncIterator and expect it to return an object which implements the Iterator API. In many cases, this will take the form of an AsyncGenerator, an object which implements this API: class Foo { async *[Symbol.asyncIterator]() {} } let f = new Foo(); console.log(f[Symbol.asyncIterator]()); // AsyncGenerator {<suspended>} The object produced by the Symbol.asyncIterator function should sequentially produce Promise instances via its next() method. This can be through explicit next() method definition or implicitly through an async generator function: class Emitter {/* w w w . d em o 2 s .c o m */ constructor(max) { this.max = max; this.asyncIdx = 0; } async *[Symbol.asyncIterator]() { while(this.asyncIdx < this.max) { yield new Promise((resolve) => resolve(this.asyncIdx++)); } } } async function asyncCount() { let emitter = new Emitter(5); for await(const x of emitter) { console.log(x); } } asyncCount(); Output: Symbol.asyncIterator is part of the ES2018 specification.

Well Known Symbol Symbol.hasInstance

ECMAScript Well Known Symbol Symbol.hasInstance is used as a property for "A method that determines if a constructor object recognizes an object as one of the constructor's instances. Called by the semantics of the instanceof operator". The instanceof operator provides a way of determining if an object instance has a prototype in its prototype chain. Typical use of the instanceof is as follows: function Demo() {} let f = new Demo(); console.log(f instanceof Demo); // true class Test {} let b = new Test(); console.log(b instanceof Test); // true In ES6, the instanceof operator is using a Symbol.hasInstance function to evaluate this relationship. The Symbol.hasInstance identifies a function which performs the same behavior but with the operands reversed: function Demo() {} let f = new Demo(); console.log(Demo[Symbol.hasInstance](f)); // true class Test {} let b = new Test(); console.log(Test[Symbol.hasInstance](b)); // true This property is defined on the Function prototype, and therefore it is automatically available by default to all function and class definitions. Because the instanceof operator will seek the property definition on the prototype chain like any other property, it is possible to redefine the function on an inherited class as a static method: class Test {} class Baz extends Test { static [Symbol.hasInstance]() { return false; } } let b = new Baz(); console.log(Test[Symbol.hasInstance](b)); // true console.log(b instanceof Test); // true console.log(Baz[Symbol.hasInstance](b)); // false console.log(b instanceof Baz); // false

Well Known Symbol Symbol.isConcatSpreadable

ECMAScript Well Known Symbol Symbol.isConcatSpreadable is used as a property for "A Boolean valued property that if true indicates that an object should be flattened to its array elements by Array.prototype.concat()". The Array.prototype.concat method in ES6 will select how to join an array-like object to the array instance based on the type of object it is passed. The value of Symbol.isConcatSpreadable allows you to override this behavior. Array objects by default will be flattened into the existing array; a value of false or falsy value will append the entire object to the array. Array-like objects by default will be appended to the array; a value of true or truthy value will flatten the array-like object into the array instance. Other objects which are not array-like will be ignored when Symbol.isConcatSpreadable is set to true. let initial = ['test']; let array = ['demo']; console.log(array[Symbol.isConcatSpreadable]); // undefined console.log(initial.concat(array)); // ['test', 'demo'] array[Symbol.isConcatSpreadable] = false; console.log(initial.concat(array)); // ['test', Array(1)] let test = { length: 1, 0: 'baz' }; console.log(test[Symbol.isConcatSpreadable]); // undefined console.log(initial.concat(test)); // ['test', {...}] test[Symbol.isConcatSpreadable] = true; console.log(initial.concat(test)); // ['test', 'baz'] let otherObject = new Set().add('qux'); console.log(otherObject[Symbol.isConcatSpreadable]); // undefined console.log(initial.concat(otherObject)); // ['test', Set(1)] otherObject[Symbol.isConcatSpreadable] = true; console.log(initial.concat(otherObject)); // ['test']

Well Known Symbol Symbol.iterator

ECMAScript Well Known Symbol Symbol.iterator is used as a property for "A method that returns the default Iterator for an object. Called by the semantics of the for-of statement". It is used to identify the function that implements the iterator API. Javascript for-of loop make use of this function to perform iteration. They will invoke the function identified by Symbol.iterator and expect it to return an object which implements the Iterator API. In many cases, this will take the form of a Generator, an object which implements this API: class Foo { *[Symbol.iterator]() {} } let f = new Foo(); console.log(f[Symbol.iterator]()); // Generator {<suspended>} Specifically, the object produced by the Symbol.iterator function should sequentially produce values via its next() method. This can be through explicit next() method definition or implicitly through a generator function: class Emitter {/*w w w. d em o2 s . c o m */ constructor(max) { this.max = max; this.idx = 0; } *[Symbol.iterator]() { while(this.idx < this.max) { yield this.idx++; } } } function count() { let emitter = new Emitter(5); for (const x of emitter) { console.log(x); } } count(); Output:

Well Known Symbol Symbol.match

ECMAScript Well Known Symbol Symbol.match is used as a property for "A regular expression method that matches the regular expression against a string. Called by the String.prototype.match() method". The String.prototype.match() method will use the function identified by Symbol.match to evaluate the expression. The regular expression prototype has this function defined by default, and therefore all regular expression instances are valid parameters to the String method by default: console.log(RegExp.prototype[Symbol.match]); //f [Symbol.match]() { [native code] } console.log('foobar'.match(/bar/)); // ["bar", index: 3, input: "foobar", groups: undefined] Providing something other than a regular expression to this method will cause it to be converted to a RegExp object. This function has a single parameter which is the string instance upon which match() is invoked. The return value is unrestricted: class FooMatcher {// w w w . de m o 2 s . c o m static [Symbol.match](target) { return target.includes('foo'); } } console.log('foobar'.match(FooMatcher)); // true console.log('barbaz'.match(FooMatcher)); // false class StringMatcher { constructor(str) { this.str = str; } [Symbol.match](target) { return target.includes(this.str); } } console.log('foobar'.match(new StringMatcher('foo'))); // true console.log('barbaz'.match(new StringMatcher('qux'))); // false

Well Known Symbol Symbol.replace

ECMAScript Well Known Symbol Symbol.replace is used as a property for "A regular expression method that replaces matched substrings of a string. Called by the String.prototype.replace() method". The String.prototype.replace() method will use the function identified by Symbol.replace to evaluate the expression. The regular expression prototype has this function defined by default, and therefore all regular expression instances are valid parameters to the String method by default: console.log(RegExp.prototype[Symbol.replace]); // f[Symbol.replace]() { [native code] } console.log('foobarbaz'.replace(/bar/, 'qux')); // 'fooquxbaz' Providing something other than a regular expression to this method will cause it to be converted to a RegExp object. This function has two parameters, the string instance upon which replace() is invoked and the replacement string. The return value is unrestricted: class FooReplacer {// w w w .d e m o 2 s . c o m static[Symbol.replace](target, replacement) { return target.split('foo').join(replacement); } } console.log('barfoobaz'.replace(FooReplacer, 'qux')); // "barquxbaz" class StringReplacer { constructor(str) { this.str = str; } [Symbol.replace](target, replacement) { return target.split(this.str).join(replacement); } } console.log('barfoobaz'.replace(new StringReplacer('foo'), 'qux')); // "barquxbaz"

Well Known Symbol Symbol.search

ECMAScript Well Known Symbol Symbol.search is used as a property for "A regular expression method that returns the index within a string that matches the regular expression. Called by the String .prototype.search() method". The String.prototype.search() method will use the function identified by Symbol.search to evaluate the expression. The regular expression prototype has this function defined by default, and therefore all regular expression instances are valid parameters to the String method by default: console.log(RegExp.prototype[Symbol.search]); // f [Symbol.search]() { [native code] } console.log('foobar'.search(/bar/)); // 3 Providing something other than a regular expression to this method will cause it to be converted to a RegExp object. This function has a single parameter which is the string instance upon which search() is invoked. The return value is unrestricted: class FooSearcher {// w ww . d e m o 2 s . c om static[Symbol.search](target) { return target.indexOf('foo'); } } console.log('foobar'.search(FooSearcher)); // 0 console.log('barfoo'.search(FooSearcher)); // 3 console.log('barbaz'.search(FooSearcher)); // -1 class StringSearcher { constructor(str) { this.str = str; } [Symbol.search](target) { return target.indexOf(this.str); } } console.log('foobar'.search(new StringSearcher('foo'))); // 0 console.log('barfoo'.search(new StringSearcher('foo'))); // 3 console.log('barbaz'.search(new StringSearcher('qux'))); // -1

Well Known Symbol Symbol.species

ECMAScript Well Known Symbol Symbol.species is used as a property for "A function valued property that is the constructor function that is used to create derived objects". This is most commonly used for build-in types which expose methods that instantiate derived objects for the return value of an instance method. Defining a static getter method with Symbol.species allows you to override the prototype definition for the newly created instance: class Bar extends Array {} class Test extends Array { static get [Symbol.species]() {// w ww . d e m o 2 s . c o m return Array; } } let bar = new Bar(); console.log(bar instanceof Array); // true console.log(bar instanceof Bar); // true bar = bar.concat('bar'); console.log(bar instanceof Array); // true console.log(bar instanceof Bar); // true let baz = new Test(); console.log(baz instanceof Array); // true console.log(baz instanceof Test); // true baz = baz.concat('baz'); console.log(baz instanceof Array); // true console.log(baz instanceof Test); // false

Well Known Symbol Symbol.split

ECMAScript Well Known Symbol Symbol.split is used as a property for "A regular expression method that splits a string at the indices that match the regular expression. Called by the String .prototype.split() method". The String.prototype.split() method will use the function identified by Symbol.split to evaluate the expression. The regular expression prototype has this function defined by default, and therefore all regular expression instances are valid parameters to the String method by default: console.log(RegExp.prototype[Symbol.split]); // f [Symbol.split]() { [native code] } console.log('footestbaz'.split(/test/)); // ['foo', 'baz'] Providing something other than a regular expression to this method will cause it to be converted to a RegExp object. This function has a single parameter which is the string instance upon which split() is invoked. The return value is unrestricted: class FooSplitter {/*w w w .d e m o2 s. c om */ static [Symbol.split](target) { return target.split('foo'); } } console.log('testfoobaz'.split(FooSplitter)); // ["test", "baz"] class StringSplitter { constructor(str) { this.str = str; } [Symbol.split](target) { return target.split(this.str); } } console.log('testfoobaz'.split(new StringSplitter('foo'))); // ["test", "baz"]

Well Known Symbol Symbol.toPrimitive

ECMAScript Well Known Symbol Symbol.toPrimitive is used as a property for "A method that converts an object to a corresponding primitive value. Called by the ToPrimitive abstract operation". There are a number of built-in operations which will attempt to coerce an object into a primitive value: a string, a number, or an unspecified primitive type. For a custom object instance, it is possible to divert this behavior by defining a function on the instance's Symbol.toPrimitive property. Based on a string parameter provided to the function, you are able to control the returned primitive: class Foo {}/*w w w . d e m o 2 s . co m */ let foo = new Foo(); console.log(3 + foo); // "3[object Object]" console.log(3 - foo); // NaN console.log(String(foo)); // "[object Object]" class Bar { constructor() { this[Symbol.toPrimitive] = function(hint) { switch (hint) { case 'number': return 3; case 'string': return 'string test'; case 'default': default: return 'default test'; } } } } let test = new Bar(); console.log(3 + test); // "3default test" console.log(3 - test); // 0 console.log(String(test)); // "string test"

Well Known Symbol Symbol.toStringTag

ECMAScript Well Known Symbol Symbol.toStringTag is used as a property for "A String valued property that is used in the creation of the default string description of an object. Accessed by the built-in method Object.prototype.toString()". Object identification via the toString() method will retrieve the instance identifier specified by Symbol.toStringTag, defaulting to Object. Built-in types have this value already specified, but custom class instances require explicit definition: let s = new Set(); console.log(s); // Set(0) {} console.log(s.toString()); // [object Set] console.log(s[Symbol.toStringTag]); // Set class Foo {}// w w w . de m o 2 s . c o m let foo = new Foo(); console.log(foo); // Foo {} console.log(foo.toString()); // [object Object] console.log(foo[Symbol.toStringTag]); // undefined class Bar { constructor() { this[Symbol.toStringTag] = 'Bar'; } } let bar = new Bar(); console.log(bar); // Bar {} console.log(bar.toString()); // [object Bar] console.log(bar[Symbol.toStringTag]); // Bar

Well Known Symbol Symbol.unscopables

ECMAScript Well Known Symbol Symbol.unscopables is used as a property for "An object valued property whose own and inherited property names are property names that are excluded from the with environment bindings of the associated object". Setting this symbol so it keys an object mapping a corresponding property to true will prevent a with environment binding, as shown here: let o = { foo: 'test' }; with (o) { console.log(foo); // test } o[Symbol.unscopables] = { foo: true }; with (o) { console.log(foo); // ReferenceError } It's not recommended to use with statement, so using Symbol.unscopables is also not recommended.

Operators

ECMA-262 describes a set of operators that can be used to manipulate data values. The operators range from mathematical operations, such as addition and subtraction, and bitwise operators to relational operators and equality operators. Operators in ECMAScript can be used on a wide range of values, including strings, numbers, Booleans, and even objects. When used on objects, operators typically call the valueOf() and/or toString() method to retrieve a value they can work with.

Unary Operators

Operators that work on only one value are called unary operators. They are the simplest operators in ECMAScript.

Increment Decrement Operators

The increment and decrement operators are taken directly from C and come in two versions: prefix and postfix. The prefix versions of the operators are placed before the variable they work on; the postfix ones are placed after the variable. To use a prefix increment, which adds 1 to a numeric value, you place two plus signs (++) in front of a variable like this: let myValue = 29; ++myValue; In this example, the prefix increment changes the value of myValue to 30 by adding 1 to its previous value of 29. This is effectively equal to the following: let myValue = 29; myValue = myValue + 1; The prefix decrement acts in a similar manner, subtracting 1 from a numeric value. To use a prefix decrement, place two minus signs (--) before a variable, as shown here: let myValue = 29; --myValue; Here the myValue variable is decremented to 28 by subtracting 1 from 29. When using either a prefix increment or a prefix decrement, the variable's value is converted before the statement is evaluated. Consider the following: let myValue = 29; let otherValue = --myValue + 2; console.log(myValue); // 28 console.log(otherValue); // 30 In this example, the variable otherValue is initialized with the decremented value of myValue plus 2. Because the decrement happens first, myValue is set to 28, and then 2 is added, resulting in 30. The prefix increment and decrement are equal in terms of order of precedence in a statement and are therefore evaluated left to right. Consider this example: let num1 = 2; let num2 = 20; let num3 = --num1 + num2; let num4 = num1 + num2; console.log(num3); // 21 console.log(num4); // 21 Here, num3 is equal to 21 because num1 is decremented to 1 before the addition occurs. The variable num4 also contains 21, because the addition is also done using the changed values. The postfix versions of increment and decrement use the same syntax (++ and --, respectively) but are placed after the variable instead of before it. Postfix increment and decrement differ from the prefix versions in one important way: the increment or decrement doesn't occur until after the containing statement has been evaluated. In certain circumstances, this difference doesn't matter, as in this example: let myValue = 29; myValue++; Moving the increment operator after the variable doesn't change what these statements do, because the increment is the only operation occurring. However, when mixed together with other operations, the difference becomes apparent, as in the following example: let num1 = 2; let num2 = 20; let num3 = num1-- + num2; let num4 = num1 + num2; console.log(num3); // 22 console.log(num4); // 21 With just one simple change in this example, using postfix decrement instead of prefix, you can see the difference. In the prefix example, num3 and num4 both ended up equal to 21, whereas this example ends with num3 equal to 22 and num4 equal to 21. The difference is that the calculation for num3 uses the original value of num1 (2) to complete the addition, whereas num4 is using the decremented value (1).

Converting Rules

All four of these operators work on any values, meaning not just integers but strings, Booleans, floating-point values, and objects. The increment and decrement operators follow these rules regarding values: When used on a string that is a valid representation of a number, convert to a number and apply the change. The variable is converted from a string to a number. When used on a string that is not a valid number, the variable's value is set to NaN. The variable is converted from a string to a number. When used on a Boolean value that is false, convert to 0 and apply the change. The variable is converted from a Boolean to a number. When used on a Boolean value that is true, convert to 1 and apply the change. The variable is converted from a Boolean to a number. When used on a floating-point value, apply the change by adding or subtracting 1. When used on an object, call its valueOf() method to get a value to work with. Apply the other rules. If the result is NaN, then call toString() and apply the other rules again. The variable is converted from an object to a number. The following example demonstrates some of these rules: let s1 = "2"; let s2 = "z"; let b = false; let f = 1.1; let o = { valueOf() { return -2; } }; s1++; // value becomes numeric 3 s2++; // value becomes NaN b++; // value becomes numeric 1 f--; // value becomes 0.10000000000000009 (due to floating-point inaccuracies) o--; // value becomes numeric -3

Unary Plus and Minus Operator

The unary plus is represented by a single plus sign (+) placed before a variable and does nothing to a numeric value, as shown in this example: let num = 25; num = +num; console.log(num); // 25 When the unary plus is applied to a nonnumeric value, it performs the same conversion as the Number() casting function: the Boolean values of false and true are converted to 0 and 1, string values are parsed according to a set of specific rules, and objects have their valueOf() and/or toString() method called to get a value to convert. The following example demonstrates the behavior of the unary plus when acting on different data types: let s1 = "01"; let s2 = "1.1"; let s3 = "z"; let b = false; let f = 1.1; let o = { valueOf() { return -1; } }; s1 = +s1; // value becomes numeric 1 s2 = +s2; // value becomes numeric 1.1 s3 = +s3; // value becomes NaN b = +b; // value becomes numeric 0 f = +f; // no change, still 1.1 o = +o; // value becomes numeric -1

unary minus

The unary minus operator's primary use is to negate a numeric value, such as converting 1 into -1. The simple case is illustrated here: let num = 25; num = -num; console.log(num); // -25 When used on a numeric value, the unary minus simply negates the value. When used on nonnumeric values, unary minus applies all of the same rules as unary plus and then negates the result, as shown here: let s1 = "01"; let s2 = "1.1"; let s3 = "z"; let b = false; let f = 1.1; let o = { valueOf() { return -1; } }; s1 = -s1; // value becomes numeric -1 s2 = -s2; // value becomes numeric -1.1 s3 = -s3; // value becomes NaN b = -b; // value becomes numeric 0 f = -f; // change to -1.1 o = -o; // value becomes numeric 1 The unary plus and minus operators are used primarily for basic arithmetic but can also be useful for conversion purposes.

Number bit format for Bitwise Operators

Bits

All numbers in ECMAScript are stored in IEEE-754 64-bit format, but the bitwise operations do not work directly on the 64-bit representation. Instead, the value is converted into a 32-bit integer, the operation takes place, and the result is converted back into 64 bits. To the developer, it appears that only the 32-bit integer exists because the 64-bit storage format is transparent. Signed integers use the first 31 of the 32 bits to represent the numeric value of the integer. The 32nd bit represents the sign of the number: 0 for positive or 1 for negative. Depending on the value of that bit, called the sign bit, the format of the rest of the number is determined. Positive numbers are stored in true binary format, with each of the 31 bits representing a power of 2, starting with the first bit (called bit 0) representing 20, the second bit represents 21. If any bits are unused, they are filled with 0 and essentially ignored. For example, the number 18 is represented as 00000000000000000000000000010010, or more succinctly as 10010. These are the five most significant bits and can be used, by themselves, to determine the actual value.

Negative numbers

Negative numbers are also stored in binary code but in a format called two's complement. The two's complement of a number is calculated in three steps: Determine the binary representation of the absolute value (for example, to find -18, first determine the binary representation of 18). Find the one's complement of the number, which essentially means that every 0 must be replaced with a 1, and vice versa. Add 1 to the result. Using this process to determine the binary representation -18, start with the binary representation of 18, which is the following: 0000 0000 0000 0000 0000 0000 0001 0010 Next, take the one's complement, which is the inverse of this number: 1111 1111 1111 1111 1111 1111 1110 1101 Finally, add 1 to the one's complement as follows: 1111 1111 1111 1111 1111 1111 1110 1101 1 --------------------------------------- 1111 1111 1111 1111 1111 1111 1110 1110 So the binary equivalent of -18 is 11111111111111111111111111101110. Keep in mind that you have no access to bit 31 when dealing with signed integers. When outputting a negative number as a binary string, you get the binary code of the absolute value preceded by a minus sign, as in this example: let num = -18; console.log(num.toString(2)); // "-10010" When you convert the number -18 to a binary string, the result is -10010. The conversion process interprets the two's complement and represents it in an arguably more logical form. By default, all integers are represented as signed in ECMAScript. In an unsigned integer, the 32nd bit doesn't represent the sign because there are only positive numbers. Unsigned integers can be larger, because the extra bit becomes part of the number instead of an indicator of the sign.

Apply bitwise operators

When you apply bitwise operators to numbers in ECMAScript, a conversion takes place behind the scenes: the 64-bit number is converted into a 32-bit number, the operation is performed, and then the 32-bit result is stored back into a 64-bit number. This gives the illusion that you're dealing with true 32-bit numbers, which makes the binary operations work in a way similar to the operations of other languages. NaN and Infinity both are treated as equivalent to 0 when used in bitwise operations. If a bitwise operator is applied to a nonnumeric value, the value is first converted into a number using the Number() function and then the bitwise operation is applied. The resulting value is a number.