• Home   /  
  • Archive by category "1"

Shell Script Array Assignment In Javascript

This part of the JavaScript section on MDN serves as a repository of facts about the JavaScript language. Read more about this reference.

Global Objects

This chapter documents all the JavaScript standard built-in objects, along with their methods and properties.

Value properties

These global properties return a simple value; they have no properties or methods.

Function properties

These global functions—functions which are called globally rather than on an object—directly return their results to the caller.

Fundamental objects

These are the fundamental, basic objects upon which all other objects are based. This includes objects that represent general objects, functions, and errors.

Numbers and dates

These are the base objects representing numbers, dates, and mathematical calculations.

Text processing

These objects represent strings and support manipulating them.

Indexed collections

These objects represent collections of data which are ordered by an index value. This includes (typed) arrays and array-like constructs.

Keyed collections

These objects represent collections which use keys; these contain elements which are iterable in the order of insertion.

Vector collections

SIMD vector data types are objects where data is arranged into lanes.

Structured data

These objects represent and interact with structured data buffers and data coded using JavaScript Object Notation (JSON).

Control abstraction objects

Reflection

Internationalization

Additions to the ECMAScript core for language-sensitive functionalities.

WebAssembly

Other

Statements

This chapter documents all the JavaScript statements and declarations.

For an alphabetical listing see the sidebar on the left.

Control flow

A block statement is used to group zero or more statements. The block is delimited by a pair of curly brackets.
Terminates the current loop, switch, or label statement and transfers program control to the statement following the terminated statement.
Terminates execution of the statements in the current iteration of the current or labeled loop, and continues execution of the loop with the next iteration.
An empty statement is used to provide no statement, although the JavaScript syntax would expect one.
Executes a statement if a specified condition is true. If the condition is false, another statement can be executed.
Evaluates an expression, matching the expression's value to a case clause, and executes statements associated with that case.
Throws a user-defined exception.
Marks a block of statements to try, and specifies a response, should an exception be thrown.

Declarations

Declares a variable, optionally initializing it to a value.
Declares a block scope local variable, optionally initializing it to a value.
Declares a read-only named constant.

Functions and classes

Declares a function with the specified parameters.
Generator Functions enable writing iterators more easily.
Declares an async function with the specified parameters.
Specifies the value to be returned by a function.
Declares a class.

Iterations

Creates a loop that executes a specified statement until the test condition evaluates to false. The condition is evaluated after executing the statement, resulting in the specified statement executing at least once.
Creates a loop that consists of three optional expressions, enclosed in parentheses and separated by semicolons, followed by a statement executed in the loop.
Iterates a specified variable over all values of object's properties. For each distinct property, a specified statement is executed.
Iterates over the enumerable properties of an object, in arbitrary order. For each distinct property, statements can be executed.
Iterates over iterable objects (including arrays, array-like objects, iterators and generators), invoking a custom iteration hook with statements to be executed for the value of each distinct property.
Creates a loop that executes a specified statement as long as the test condition evaluates to true. The condition is evaluated before executing the statement.

Others

Invokes any available debugging functionality. If no debugging functionality is available, this statement has no effect.
Used to export functions to make them available for imports in external modules, another scripts.
Used to import functions exported from an external module, another script.
Provides a statement with an identifier that you can refer to using a or statement.
Extends the scope chain for a statement.

Expressions and operators

This chapter documents all the JavaScript expressions and operators.

For an alphabetical listing see the sidebar on the left.

Primary expressions

Basic keywords and general expressions in JavaScript.

The keyword refers to the function's execution context.
The keyword defines a function expression.
The keyword defines a class expression.
The keyword defines a generator function expression.
Pause and resume a generator function.
Delegate to another generator function or iterable object.
The defines an async function expression.
Pause and resume an async function and wait for the promise's resolution/rejection.
Array initializer/literal syntax.
Object initializer/literal syntax.
Regular expression literal syntax.
Grouping operator.

Left-hand-side expressions

Left values are the destination of an assignment.

Property accessors
Member operators provide access to a property or method of an object
( and ).
The operator creates an instance of a constructor.
new.target
In constructors, refers to the constructor that was invoked by .
The keyword calls the parent constructor.
Spread syntax allows an expression to be expanded in places where multiple arguments (for function calls) or multiple elements (for array literals) are expected.

Increment and decrement

Postfix/prefix increment and postfix/prefix decrement operators.

Postfix increment operator.
Postfix decrement operator.
Prefix increment operator.
Prefix decrement operator.

Unary operators

A unary operation is operation with only one operand.

The operator deletes a property from an object.
The operator discards an expression's return value.
The operator determines the type of a given object.
The unary plus operator converts its operand to Number type.
The unary negation operator converts its operand to Number type and then negates it.
Bitwise NOT operator.
Logical NOT operator.

Arithmetic operators

Arithmetic operators take numerical values (either literals or variables) as their operands and return a single numerical value.

Addition operator.
Subtraction operator.
Division operator.
Multiplication operator.
Remainder operator.
Exponentiation operator.

Relational operators

A comparison operator compares its operands and returns a value based on whether the comparison is true.

The operator determines whether an object has a given property.
The operator determines whether an object is an instance of another object.
Less than operator.
Greater than operator.
Less than or equal operator.
Greater than or equal operator.

Equality operators

The result of evaluating an equality operator is always of type based on whether the comparison is true.

Equality operator.
Inequality operator.
Identity operator.
Nonidentity operator.

Bitwise shift operators

Operations to shift all bits of the operand.

Bitwise left shift operator.
Bitwise right shift operator.
Bitwise unsigned right shift operator.

Binary bitwise operators

Bitwise operators treat their operands as a set of 32 bits (zeros and ones) and return standard JavaScript numerical values.

Bitwise AND.
Bitwise OR.
Bitwise XOR.

Binary logical operators

Logical operators are typically used with boolean (logical) values, and when they are, they return a boolean value.

Logical AND.
Logical OR.

Conditional (ternary) operator

The conditional operator returns one of two values based on the logical value of the condition.

Assignment operators

An assignment operator assigns a value to its left operand based on the value of its right operand.

Assignment operator.
Multiplication assignment.
Division assignment.
Remainder assignment.
Addition assignment.
Subtraction assignment
Left shift assignment.
Right shift assignment.
Unsigned right shift assignment.
Bitwise AND assignment.
Bitwise XOR assignment.
Bitwise OR assignment.

Destructuring assignment allows you to assign the properties of an array or object to variables using syntax that looks similar to array or object literals.

Comma operator

The comma operator allows multiple expressions to be evaluated in a single statement and returns the result of the last expression.

Non-standard features

Legacy generator function
The keyword can be used to define a legacy generator function inside an expression. To make the function a legacy generator, the function body should contains at least one expression.
Expression closures
The expression closure syntax is a shorthand for writing simple function.
Array comprehensions.
Generator comprehensions.

Functions

This chapter documents how to work with JavaScript functions to develop your applications.

Additional reference pages

Document Tags and Contributors

 Contributors to this page:sideshowbarker, vanessadacosta, Jeremie, SphinxKnight, 469067375, fscholz, makaveli, x2357, LJHarb, Mingun, TwelveBaud, tokenquestion, dmon2013, raztus, emilNikolov, Timmi, ananta_eka, gsvelto, Sheppy, Norbert, ethertank, MattBrubeck, saneyuki_s, deridder, Wladimir_Palant, Potappo, evilpie, Sevenspade, syssgx, matteodelabre, Vinícius Albuquerque, user01, Dyhan81, Dionys, skorpan, Brettz9, Paul.heartj, Cnmahj, Yuichirou, Nickolay, DavidCary, HeroreV, Momoass, Takenbot, Dria, Niklas, Maian, Marcoos, Callek, stav

 Last updated by:sideshowbarker,

Why a re-introduction? Because JavaScript is notorious for being the world's most misunderstood programming language. It is often derided as being a toy, but beneath its layer of deceptive simplicity, powerful language features await. JavaScript is now used by an incredible number of high-profile applications, showing that deeper knowledge of this technology is an important skill for any web or mobile developer.

It's useful to start with an overview of the language's history. JavaScript was created in 1995 by Brendan Eich while he was an engineer at Netscape. JavaScript was first released with Netscape 2 early in 1996. It was originally going to be called LiveScript, but it was renamed in an ill-fated marketing decision that attempted to capitalize on the popularity of Sun Microsystem's Java language — despite the two having very little in common. This has been a source of confusion ever since.

Several months later, Microsoft released JScript with Internet Explorer 3. It was a mostly-compatible JavaScript work-alike. Several months after that, Netscape submitted JavaScript to Ecma International, a European standards organization, which resulted in the first edition of the ECMAScript standard that year. The standard received a significant update as ECMAScript edition 3 in 1999, and it has stayed pretty much stable ever since. The fourth edition was abandoned, due to political differences concerning language complexity. Many parts of the fourth edition formed the basis for ECMAScript edition 5, published in December of 2009, and for the 6th major edition of the standard, published in June of 2015.

Because it is more familiar, we will refer to ECMAScript as "JavaScript" from this point on.

Unlike most programming languages, the JavaScript language has no concept of input or output. It is designed to run as a scripting language in a host environment, and it is up to the host environment to provide mechanisms for communicating with the outside world. The most common host environment is the browser, but JavaScript interpreters can also be found in a huge list of other places, including Adobe Acrobat, Adobe Photoshop, SVG images, Yahoo's Widget engine, server-side environments such as Node.js, NoSQL databases like the open source Apache CouchDB, embedded computers, complete desktop environments like GNOME (one of the most popular GUIs for GNU/Linux operating systems), and others.

Overview

JavaScript is a multi-paradigm, dynamic language with types and operators, standard built-in objects, and methods. Its syntax is based on the Java and C languages — many structures from those languages apply to JavaScript as well. JavaScript supports object-oriented programming with object prototypes, instead of classes (see more about prototypical inheritance and ES2015 classes). JavaScript also supports functional programming — functions are objects, giving functions the capacity to hold executable code and be passed around like any other object.

Let's start off by looking at the building blocks of any language: the types. JavaScript programs manipulate values, and those values all belong to a type. JavaScript's types are:

... oh, and and , which are ... slightly odd. And , which is a special kind of object. And and , which are objects that you get for free. And to be technically accurate, functions are just a special type of object. So the type diagram looks more like this:

And there are some built-in types as well. Things are a lot easier if we stick with the first diagram, however, so we'll discuss the types listed there for now.

Numbers

Numbers in JavaScript are "double-precision 64-bit format IEEE 754 values", according to the spec. This has some interesting consequences. There's no such thing as an integer in JavaScript, so you have to be a little careful with your arithmetic if you're used to math in C or Java.

Also, watch out for stuff like:

0.1 + 0.2 == 0.30000000000000004;

In practice, integer values are treated as 32-bit ints, and some implementations even store it that way until they are asked to perform an instruction that's valid on a Number but not on a 32-bit integer. This can be important for bit-wise operations.

The standard arithmetic operators are supported, including addition, subtraction, modulus (or remainder) arithmetic, and so forth. There's also a built-in object that we forgot to mention earlier called that provides advanced mathematical functions and constants:

Math.sin(3.5); var circumference = 2 * Math.PI * r;

You can convert a string to an integer using the built-in function. This takes the base for the conversion as an optional second argument, which you should always provide:

parseInt('123', 10); // 123 parseInt('010', 10); // 10

In older browsers, strings beginning with a "0" are assumed to be in octal (radix 8), but this hasn't been the case since 2013 or so. Unless you're certain of your string format, you can get surprising results on those older browsers:

parseInt('010'); // 8 parseInt('0x10'); // 16

Here, we see the function treat the first string as octal due to the leading 0, and the second string as hexadecimal due to the leading "0x". The hexadecimal notation is still in place; only octal has been removed.

If you want to convert a binary number to an integer, just change the base:

parseInt('11', 2); // 3

Similarly, you can parse floating point numbers using the built-in function. Unlike its cousin, always uses base 10.

You can also use the unary operator to convert values to numbers:

+ '42'; // 42 + '010'; // 10 + '0x10'; // 16

A special value called (short for "Not a Number") is returned if the string is non-numeric:

parseInt('hello', 10); // NaN

is toxic: if you provide it as an operand to any mathematical operation the result will also be :

NaN + 5; // NaN

You can test for using the built-in function:

isNaN(NaN); // true

JavaScript also has the special values and :

1 / 0; // Infinity -1 / 0; // -Infinity

You can test for , and values using the built-in function:

isFinite(1 / 0); // false isFinite(-Infinity); // false isFinite(NaN); // false

The and functions parse a string until they reach a character that isn't valid for the specified number format, then return the number parsed up to that point. However the "+" operator simply converts the string to if there is an invalid character contained within it. Just try parsing the string "10.2abc" with each method by yourself in the console and you'll understand the differences better.

Strings

Strings in JavaScript are sequences of Unicode characters. This should be welcome news to anyone who has had to deal with internationalization. More accurately, they are sequences of UTF-16 code units; each code unit is represented by a 16-bit number. Each Unicode character is represented by either 1 or 2 code units.

If you want to represent a single character, you just use a string consisting of that single character.

To find the length of a string (in code units), access its property:

'hello'.length; // 5

There's our first brush with JavaScript objects! Did we mention that you can use strings like objects too? They have methods as well that allow you to manipulate the string and access information about the string:

'hello'.charAt(0); // "h" 'hello, world'.replace('hello', 'goodbye'); // "goodbye, world" 'hello'.toUpperCase(); // "HELLO"

Other types

JavaScript distinguishes between , which is a value that indicates a deliberate non-value (and is only accessible through the keyword), and , which is a value of type that indicates an uninitialized value — that is, a value hasn't even been assigned yet. We'll talk about variables later, but in JavaScript it is possible to declare a variable without assigning a value to it. If you do this, the variable's type is . is actually a constant.

JavaScript has a boolean type, with possible values and (both of which are keywords.) Any value can be converted to a boolean according to the following rules:

  1. , , empty strings (), , , and all become
  2. All other values become

You can perform this conversion explicitly using the function:

Boolean(''); // false Boolean(234); // true

However, this is rarely necessary, as JavaScript will silently perform this conversion when it expects a boolean, such as in an statement (see below). For this reason, we sometimes speak simply of "true values" and "false values," meaning values that become and , respectively, when converted to booleans. Alternatively, such values can be called "truthy" and "falsy", respectively.

Boolean operations such as (logical and), (logical or), and (logical not) are supported; see below.

Variables

New variables in JavaScript are declared using one of three keywords: , , or .

allows you to declare block-level variables. The declared variable is available from the block it is enclosed in.

let a; let name = 'Simon';

The following is an example of scope with a variable declared with :

// myLetVariable is *not* visible out here for (let myLetVariable = 0; myLetVariable < 5; myLetVariable++) { // myLetVariable is only visible in here } // myLetVariable is *not* visible out here

allows you to declare variables whose values are never intended to change. The variable is available from the block it is declared in.

const Pi = 3.14; // variable Pi is set Pi = 1; // will throw an error because you cannot change a constant variable.


is the most common declarative keyword. It does not have the restrictions that the other two keywords have. This is because it was traditionally the only way to declare a variable in JavaScript. A variable declared with the keyword is available from the function it is declared in.

var a; var name = 'Simon';

An example of scope with a variable declared with :

// myVarVariable *is* visible out here for (var myVarVariable = 0; myVarVariable < 5; myVarVariable++) { // myVarVariable is visible to the whole function } // myVarVariable *is* visible out here

If you declare a variable without assigning any value to it, its type is .

An important difference between JavaScript and other languages like Java is that in JavaScript, blocks do not have scope; only functions have a scope. So if a variable is defined using in a compound statement (for example inside an control structure), it will be visible to the entire function. However, starting with ECMAScript 2015, and declarations allow you to create block-scoped variables.

Operators

JavaScript's numeric operators are , , , and which is the remainder operator (which is not the same as modulo.) Values are assigned using , and there are also compound assignment statements such as and . These extend out to .

x += 5; x = x + 5;

You can use and to increment and decrement respectively. These can be used as a prefix or postfix operators.

The operator also does string concatenation:

'hello' + ' world'; // "hello world"

If you add a string to a number (or other value) everything is converted in to a string first. This might catch you up:

'3' + 4 + 5; // "345" 3 + 4 + '5'; // "75"

Adding an empty string to something is a useful way of converting it to a string itself.

Comparisons in JavaScript can be made using , , and . These work for both strings and numbers. Equality is a little less straightforward. The double-equals operator performs type coercion if you give it different types, with sometimes interesting results:

123 == '123'; // true 1 == true; // true

To avoid type coercion, use the triple-equals operator:

123 === '123'; // false 1 === true; // false

There are also and operators.

JavaScript also has bitwise operations. If you want to use them, they're there.

Control structures

JavaScript has a similar set of control structures to other languages in the C family. Conditional statements are supported by and ; you can chain them together if you like:

var name = 'kittens'; if (name == 'puppies') { name += ' woof'; } else if (name == 'kittens') { name += ' meow'; } else { name += '!'; } name == 'kittens meow';

JavaScript has loops and loops. The first is good for basic looping; the second for loops where you wish to ensure that the body of the loop is executed at least once:

while (true) { // an infinite loop! } var input; do { input = get_input(); } while (inputIsNotValid(input));

JavaScript's loop is the same as that in C and Java: it lets you provide the control information for your loop on a single line.

for (var i = 0; i < 5; i++) { // Will execute 5 times }

JavaScript also contains two other prominent for loops: ...

for (let value of array) { // do something with value }

and ...:

for (let property in object) { // do something with object property }

The and operators use short-circuit logic, which means whether they will execute their second operand is dependent on the first. This is useful for checking for null objects before accessing their attributes:

var name = o && o.getName();

Or for caching values (when falsy values are invalid):

var name = cachedName || (cachedName = getName());

JavaScript has a ternary operator for conditional expressions:

var allowed = (age > 18) ? 'yes' : 'no';

The statement can be used for multiple branches based on a number or string:

switch (action) { case 'draw': drawIt(); break; case 'eat': eatIt(); break; default: doNothing(); }

If you don't add a statement, execution will "fall through" to the next level. This is very rarely what you want — in fact it's worth specifically labeling deliberate fallthrough with a comment if you really meant it to aid debugging:

switch (a) { case 1: // fallthrough case 2: eatIt(); break; default: doNothing(); }

The default clause is optional. You can have expressions in both the switch part and the cases if you like; comparisons take place between the two using the operator:

switch (1 + 3) { case 2 + 2: yay(); break; default: neverhappens(); }

Objects

JavaScript objects can be thought of as simple collections of name-value pairs. As such, they are similar to:

  • Dictionaries in Python.
  • Hashes in Perl and Ruby.
  • Hash tables in C and C++.
  • HashMaps in Java.
  • Associative arrays in PHP.

The fact that this data structure is so widely used is a testament to its versatility. Since everything (bar core types) in JavaScript is an object, any JavaScript program naturally involves a great deal of hash table lookups. It's a good thing they're so fast!

The "name" part is a JavaScript string, while the value can be any JavaScript value — including more objects. This allows you to build data structures of arbitrary complexity.

There are two basic ways to create an empty object:

var obj = new Object();

And:

var obj = {};

These are semantically equivalent; the second is called object literal syntax and is more convenient. This syntax is also the core of JSON format and should be preferred at all times.

Object literal syntax can be used to initialize an object in its entirety:

var obj = { name: 'Carrot', for: 'Max', // 'for' is a reserved word, use '_for' instead. details: { color: 'orange', size: 12 } };

Attribute access can be chained together:

obj.details.color; // orange obj['details']['size']; // 12

The following example creates an object prototype, and an instance of that prototype, .

function Person(name, age) { this.name = name; this.age = age; } // Define an object var you = new Person('You', 24); // We are creating a new person named "You" aged 24.

Once created, an object's properties can again be accessed in one of two ways:

//dot notation obj.name = 'Simon'; var name = obj.name;

And...

// bracket notation obj['name'] = 'Simon'; var name = obj['name']; // can use a variable to define a key var user = prompt('what is your key?') obj[user] = prompt('what is its value?')

These are also semantically equivalent. The second method has the advantage that the name of the property is provided as a string, which means it can be calculated at run-time. However, using this method prevents some JavaScript engine and minifier optimizations being applied. It can also be used to set and get properties with names that are reserved words:

obj.for = 'Simon'; // Syntax error, because 'for' is a reserved word obj['for'] = 'Simon'; // works fine

Starting in ECMAScript 5, reserved words may be used as object property names "in the buff". This means that they don't need to be "clothed" in quotes when defining object literals. See the ES5 Spec.

For more on objects and prototypes see Object.prototype. For an explanation of object prototypes and the object prototype chains see Inheritance and the prototype chain.

Starting in ECMAScript 2015, object keys can be defined by the variable using bracket notation upon being created. is possible instead of just .

Arrays

Arrays in JavaScript are actually a special type of object. They work very much like regular objects (numerical properties can naturally be accessed only using syntax) but they have one magic property called ''. This is always one more than the highest index in the array.

One way of creating arrays is as follows:

var a = new Array(); a[0] = 'dog'; a[1] = 'cat'; a[2] = 'hen'; a.length; // 3

A more convenient notation is to use an array literal:

var a = ['dog', 'cat', 'hen']; a.length; // 3

Note that isn't necessarily the number of items in the array. Consider the following:

var a = ['dog', 'cat', 'hen']; a[100] = 'fox'; a.length; // 101

Remember — the length of the array is one more than the highest index.

If you query a non-existent array index, you'll get a value of  in return:

typeof a[90]; // undefined

If you take the above about and into account, you can iterate over an array using the following loop:

for (var i = 0; i < a.length; i++) { // Do something with a[i] }

ECMAScript introduced the more concise ... loop for iterable objects such as arrays:

for (const currentValue of a) { // Do something with currentValue }

You could also iterate over an array using a ... loop. But if someone added new properties to , they would also be iterated over by this loop. Therefore this loop type is not recommended for arrays.

Another way of iterating over an array that was added with ECMAScript 5 is :

['dog', 'cat', 'hen'].forEach(function(currentValue, index, array) { // Do something with currentValue or array[index] });

If you want to append an item to an array simply do it like this:

a.push(item);

Arrays come with a number of methods. See also the full documentation for array methods.

Method nameDescription
Returns a string with the of each element separated by commas.
Returns a string with the of each element separated by commas.
Returns a new array with the items added on to it.
Converts the array to a string — with values delimited by the param
Removes and returns the last item.
Appends items to the end of the array.
Reverses the array.
Removes and returns the first item.
Returns a sub-array.
Takes an optional comparison function.
Lets you modify an array by deleting a section and replacing it with more items.
Prepends items to the start of the array.

Functions

Along with objects, functions are the core component in understanding JavaScript. The most basic function couldn't be much simpler:

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

This demonstrates a basic function. A JavaScript function can take 0 or more named parameters. The function body can contain as many statements as you like and can declare its own variables which are local to that function. The statement can be used to return a value at any time, terminating the function. If no return statement is used (or an empty return with no value), JavaScript returns .

The named parameters turn out to be more like guidelines than anything else. You can call a function without passing the parameters it expects, in which case they will be set to .

add(); // NaN // You can't perform addition on undefined

You can also pass in more arguments than the function is expecting:

add(2, 3, 4); // 5 // added the first two; 4 was ignored

That may seem a little silly, but functions have access to an additional variable inside their body called , which is an array-like object holding all of the values passed to the function. Let's re-write the add function to take as many values as we want:

function add() { var sum = 0; for (var i = 0, j = arguments.length; i < j; i++) { sum += arguments[i]; } return sum; } add(2, 3, 4, 5); // 14

That's really not any more useful than writing though. Let's create an averaging function:

function avg() { var sum = 0; for (var i = 0, j = arguments.length; i < j; i++) { sum += arguments[i]; } return sum / arguments.length; } avg(2, 3, 4, 5); // 3.5

This is pretty useful, but it does seem a little verbose. To diminish this code a bit more we can look at substituting the use of the arguments array through Rest parameter syntax. In this way, we can pass in any number of arguments into the function while keeping our code minimal. The rest parameter operator is used in function parameter lists with the format: ...variable and it will include within that variable the entire list of uncaptured arguments that the function was called with. We will also replace the for loop with a for...of loop to return the values within our variable.

function avg(...args) { var sum = 0; for (let value of args) { sum += value; } return sum / args.length; } avg(2, 3, 4, 5); // 3.5

In the above code, the variable args holds all the values that were passed into the function.

It is important to note that wherever the rest parameter operator is placed in a function declaration it will store all arguments after its declaration, but not before. i.e. functionavg(firstValue, ...args)will store the first value passed into the function in the firstValue variable and the remaining arguments in args. Another useful function but it does lead us to a new problem. The function takes a comma-separated list of arguments — but what if you want to find the average of an array? You could just rewrite the function as follows:

function avgArray(arr) { var sum = 0; for (var i = 0, j = arr.length; i < j; i++) { sum += arr[i]; } return sum / arr.length; } avgArray([2, 3, 4, 5]); // 3.5

But it would be nice to be able to reuse the function that we've already created. Luckily, JavaScript lets you call a function with an arbitrary array of arguments, using the method of any function object.

avg.apply(null, [2, 3, 4, 5]); // 3.5

The second argument to is the array to use as arguments; the first will be discussed later on. This emphasizes the fact that functions are objects too.

You can achieve the same result using the spread operator in the function call.

For instance:

JavaScript lets you create anonymous functions.

var avg = function() { var sum = 0; for (var i = 0, j = arguments.length; i < j; i++) { sum += arguments[i]; } return sum / arguments.length; };

This is semantically equivalent to the form. It's extremely powerful, as it lets you put a full function definition anywhere that you would normally put an expression. This enables all sorts of clever tricks. Here's a way of "hiding" some local variables — like block scope in C:

var a = 1; var b = 2; (function() { var b = 3; a += b; })(); a; // 4 b; // 2

JavaScript allows you to call functions recursively. This is particularly useful for dealing with tree structures, such as those found in the browser DOM.

function countChars(elm) { if (elm.nodeType == 3) { // TEXT_NODE return elm.nodeValue.length; } var count = 0; for (var i = 0, child; child = elm.childNodes[i]; i++) { count += countChars(child); } return count; }

This highlights a potential problem with anonymous functions: how do you call them recursively if they don't have a name? JavaScript lets you name function expressions for this. You can use named IIFEs (Immediately Invoked Function Expressions) as shown below:

var charsInBody = (function counter(elm) { if (elm.nodeType == 3) { // TEXT_NODE return elm.nodeValue.length; } var count = 0; for (var i = 0, child; child = elm.childNodes[i]; i++) { count += counter(child); } return count; })(document.body);

The name provided to a function expression as above is only available to the function's own scope. This allows more optimizations to be done by the engine and results in more readable code. The name also shows up in the debugger and some stack traces, which can save you time when debugging.

Note that JavaScript functions are themselves objects — like everything else in JavaScript — and you can add or change properties on them just like we've seen earlier in the Objects section.

Custom objects

For a more detailed discussion of object-oriented programming in JavaScript, see Introduction to Object-Oriented JavaScript.

In classic Object Oriented Programming, objects are collections of data and methods that operate on that data. JavaScript is a prototype-based language that contains no class statement, as you'd find in C++ or Java (this is sometimes confusing for programmers accustomed to languages with a class statement). Instead, JavaScript uses functions as classes. Let's consider a person object with first and last name fields. There are two ways in which the name might be displayed: as "first last" or as "last, first". Using the functions and objects that we've discussed previously, we could display the data like this:

function makePerson(first, last) { return { first: first, last: last }; } function personFullName(person) { return person.first + ' ' + person.last; } function personFullNameReversed(person) { return person.last + ', ' + person.first; } s = makePerson('Simon', 'Willison'); personFullName(s); // "Simon Willison" personFullNameReversed(s); // "Willison, Simon"

This works, but it's pretty ugly. You end up with dozens of functions in your global namespace. What we really need is a way to attach a function to an object. Since functions are objects, this is easy:

function makePerson(first, last) { return { first: first, last: last, fullName: function() { return this.first + ' ' + this.last; }, fullNameReversed: function() { return this.last + ', ' + this.first; } }; } s = makePerson('Simon', 'Willison'); s.fullName(); // "Simon Willison" s.fullNameReversed(); // "Willison, Simon"

There's something here we haven't seen before: the keyword. Used inside a function, refers to the current object. What that actually means is specified by the way in which you called that function. If you called it using dot notation or bracket notation on an object, that object becomes . If dot notation wasn't used for the call, refers to the global object.

Note that is a frequent cause of mistakes. For example:

s = makePerson('Simon', 'Willison'); var fullName = s.fullName; fullName(); // undefined undefined

When we call alone, without using , is bound to the global object. Since there are no global variables called or we get for each one.

We can take advantage of the keyword to improve our function:

function Person(first, last) { this.first = first; this.last = last; this.fullName = function() { return this.first + ' ' + this.last; }; this.fullNameReversed = function() { return this.last + ', ' + this.first; }; } var s = new Person('Simon', 'Willison');

We have introduced another keyword: . is strongly related to . It creates a brand new empty object, and then calls the function specified, with set to that new object. Notice though that the function specified with does not return a value but merely modifies the object. It's that returns the object to the calling site. Functions that are designed to be called by are called constructor functions. Common practice is to capitalize these functions as a reminder to call them with .

The improved function still has the same pitfall with calling alone.

Our person objects are getting better, but there are still some ugly edges to them. Every time we create a person object we are creating two brand new function objects within it — wouldn't it be better if this code was shared?

function personFullName() { return this.first + ' ' + this.last; } function personFullNameReversed() { return this.last + ', ' + this.first; } function Person(first, last) { this.first = first; this.last = last; this.fullName = personFullName; this.fullNameReversed = personFullNameReversed; }

That's better: we are creating the method functions only once, and assigning references to them inside the constructor. Can we do any better than that? The answer is yes:

function Person(first, last) { this.first = first; this.last = last; } Person.prototype.fullName = function() { return this.first + ' ' + this.last; }; Person.prototype.fullNameReversed = function() { return this.last + ', ' + this.first; };

is an object shared by all instances of . It forms part of a lookup chain (that has a special name, "prototype chain"): any time you attempt to access a property of that isn't set, JavaScript will check to see if that property exists there instead. As a result, anything assigned to becomes available to all instances of that constructor via the object.

This is an incredibly powerful tool. JavaScript lets you modify something's prototype at any time in your program, which means you can add extra methods to existing objects at runtime:

s = new Person('Simon', 'Willison'); s.firstNameCaps(); // TypeError on line 1: s.firstNameCaps is not a function Person.prototype.firstNameCaps = function() { return this.first.toUpperCase(); }; s.firstNameCaps(); // "SIMON"

Interestingly, you can also add things to the prototype of built-in JavaScript objects. Let's add a method to that returns that string in reverse:

var s = 'Simon'; s.reversed(); // TypeError on line 1: s.reversed is not a function String.prototype.reversed = function() { var r = ''; for (var i = this.length - 1; i >= 0; i--) { r += this[i]; } return r; }; s.reversed(); // nomiS

Our new method even works on string literals!

'This can now be reversed'.reversed(); // desrever eb won nac sihT

As mentioned before, the prototype forms part of a chain. The root of that chain is , whose methods include — it is this method that is called when you try to represent an object as a string. This is useful for debugging our objects:

var s = new Person('Simon', 'Willison'); s.toString(); // [object Object] Person.prototype.toString = function() { return '<Person: ' + this.fullName() + '>'; } s.toString(); // "<Person: Simon Willison>"

Remember how had a null first argument? We can revisit that now. The first argument to is the object that should be treated as ''. For example, here's a trivial implementation of :

function trivialNew(constructor, ...args) { var o = {}; // Create an object constructor.apply(o, args); return o; }

This isn't an exact replica of as it doesn't set up the prototype chain (it would be difficult to illustrate). This is not something you use very often, but it's useful to know about. In this snippet, (including the ellipsis) is called the "rest arguments" — as the name implies, this contains the rest of the arguments.

Calling

var bill = trivialNew(Person, 'William', 'Orange');

is therefore almost equivalent to

var bill = new Person('William', 'Orange');

has a sister function named , which again lets you set but takes an expanded argument list as opposed to an array.

function lastNameCaps() { return this.last.toUpperCase(); } var s = new Person('Simon', 'Willison'); lastNameCaps.call(s); // Is the same as: s.lastNameCaps = lastNameCaps; s.lastNameCaps(); // WILLISON

Inner functions

JavaScript function declarations are allowed inside other functions. We've seen this once before, with an earlier function. An important detail of nested functions in JavaScript is that they can access variables in their parent function's scope:

function parentFunc() { var a = 1; function nestedFunc() { var b = 4; // parentFunc can't use this   return a + b; } return nestedFunc(); // 5 }

This provides a great deal of utility in writing more maintainable code. If a function relies on one or two other functions that are not useful to any other part of your code, you can nest those utility functions inside the function that will be called from elsewhere. This keeps the number of functions that are in the global scope down, which is always a good thing.

This is also a great counter to the lure of global variables. When writing complex code it is often tempting to use global variables to share values between multiple functions — which leads to code that is hard to maintain. Nested functions can share variables in their parent, so you can use that mechanism to couple functions together when it makes sense without polluting your global namespace — "local globals" if you like. This technique should be used with caution, but it's a useful ability to have.

Closures

This leads us to one of the most powerful abstractions that JavaScript has to offer — but also the most potentially confusing. What does this do?

function makeAdder(a) { return function(b) { return a + b; }; } var x = makeAdder(5); var y = makeAdder(20); x(6); // ? y(7); // ?

The name of the function should give it away: it creates new 'adder' functions, each of which, when called with one argument, adds it to the argument that it was created with.

What's happening here is pretty much the same as was happening with the inner functions earlier on: a function defined inside another function has access to the outer function's variables. The only difference here is that the outer function has returned, and hence common sense would seem to dictate that its local variables no longer exist. But they do still exist — otherwise, the adder functions would be unable to work. What's more, there are two different "copies" of 's local variables — one in which is 5 and the other one where  is 20. So the result of that function calls is as follows:

x(6); // returns 11 y(7); // returns 27

Here's what's actually happening. Whenever JavaScript executes a function, a 'scope' object is created to hold the local variables created within that function. It is initialized with any variables passed in as function parameters. This is similar to the global object that all global variables and functions live in, but with a couple of important differences: firstly, a brand new scope object is created every time a function starts executing, and secondly, unlike the global object (which is accessible as and in browsers as ) these scope objects cannot be directly accessed from your JavaScript code. There is no mechanism for iterating over the properties of the current scope object, for example.

So when is called, a scope object is created with one property: , which is the argument passed to the function. then returns a newly created function. Normally JavaScript's garbage collector would clean up the scope object created for at this point, but the returned function maintains a reference back to that scope object. As a result, the scope object will not be garbage-collected until there are no more references to the function object that returned.

Scope objects form a chain called the scope chain, similar to the prototype chain used by JavaScript's object system.

A closure is the combination of a function and the scope object in which it was created. Closures let you save state — as such, they can often be used in place of objects. You can find several excellent introductions to closures.

One thought on “Shell Script Array Assignment In Javascript

Leave a comment

L'indirizzo email non verrà pubblicato. I campi obbligatori sono contrassegnati *