Can I Register A Callback Whenever An Element Is Pushed To An Array
Chapter 5. Working with Arrays and Loops
5.0. Introduction
An array is an ordered drove of elements. In JavaScript, an array can be created using formal object notation, or it can be initialized using literal notation, as demonstrated in the following code:
var arrObject = new Array("val1", "val2"); // array as object var arrLiteral = ["val1", "val2"]; // array literal
To the programmer, there is no difference: you tin invoke an Assortment
method on both a literal and an object. Even so, to the JavaScript engine, an array literal has to be reinterpreted each time information technology's accessed, especially when used in a part phone call. On the positive side, though, array literals can supervene upon the need for temporary variables, especially when sending values to a function.
A new Array
object is created using the new
operator, equally follows:
var arrObject = new Array();
You tin can also create a new assortment that has some values:
var arrObject = new Array("val1","val2");
You can create an array literal by using foursquare brackets to hold the array values. For instance, y'all tin can define an array literal and assign it to a variable:
var arrLiteral = ["val1","val2","val3"];
You can also create, and apply, a literal array in a role or method call:
someFunction("param1", ["val1","val2"]);
Note, though, that when yous pass a variable containing an array literal to a function, information technology is passed past reference—the same as passing a variable holding an Assortment
object. Changes to the variable in the part are reflected exterior of the part:
office chgArray(arr) { arr[0] = "surprise!"; } var newArray = new Array("val1", "val2"); var newLiteral = ["val1","val2"]; chgArray(newArray); chgArray(newLiteral); alert(newArray); // prints surprise!,val2 warning(newLiteral); // prints surprise!,val2
An array, whether literal or object, can concur values of dissimilar information types:
var arrObject = new Array("val1", 34, true); // string, number, boolean var arrLiteral = [arrObject, "val2", 18, false); // object, cord, number, boolean
You can print out an assortment; the JavaScript engine will automatically convert the assortment into a cord representation:
alarm(arrLiteral); // prints out val1,34,truthful,val2,18,fake
In this case, the JavaScript engine makes the assortment-to-string conversion for both the array literal and the array object contained equally an element within the assortment literal.
Assortment elements can be accessed directly, using square brackets containing their index (position in the array). In addition, array elements tin can exist set using the same index, which automatically creates the assortment element if it doesn't exist:
var arrObject = new Array(); arrObject[0] = "true cat"; // array at present has one element alert(arrObject[0]); // prints cat
Arrays in JavaScript are naught-based, which means the first chemical element index is zilch, and the last chemical element is at the array length, minus 1:
var farmAnimals = new Array("cat","dog","horse","sus scrofa"); alert(farmAnimals[0]); // print cat warning(farmAnimals[iii]); // impress pig
Not all array elements take to be defined when created. For case, if y'all create an assortment literal, you can use commas to delimit array elements that don't however be:
var arrLiteral = ["val1",,"val3"];
In this code, the second array element is currently undefined
. You can't apply the empty comma, though, to add together an undefined assortment element to the end of the array: JavaScript volition just ignore information technology.
To create an array of several undefined elements, y'all can provide an assortment length when creating an assortment:
var largeCollection = new Array(100); // a new assortment with 100 undefined elements
One you've created an array, using Array
object or literal notation, you tin can access the assortment elements in a loop, or utilise any number of array methods.
5.ane. Looping Through an Array
Problem
You want to easily access all elements of an array.
Solution
The most mutual approach to accessing an array is to utilise a for
loop:
var mammals = new Array("cat","dog","human being","whale","seal"); var animalString = ""; for (var i = 0; i < mammals. length; i++) { animalString += mammals[i] + " "; } alert(animalString);
Discussion
A for
loop can be used to access every element of an array. The array begins at aught, and the array property length
is used to set the loop end.
Sometimes, though, you don't want to admission every element of the assortment. For instance, yous might desire to traverse an array until you find either a specific element, or whatsoever element that meets (or doesn't meet) a certain criteria. In these cases, y'all'll desire to use a while
loop and test the assortment elements:
var numArray = new Array(i,4,66,123,240,444,555); var i = 0; while (numArray[i] < 100) { alert(numArray[i++]); }
Observe that the index counter, i
, is incremented as information technology's used to access an array element. The use of i++
means that the existing value of i
is accessed showtime, and so the variable is incremented.
5.ii. Creating a Multidimensional Array
Problem
You want to create a multidimensional array (an array of arrays).
Solution
Create an array in which each element is likewise an array. For example, to create an array with three elements, each of which is also an assortment of iii elements containing, respectively, cord, number, and array literals, apply the code snippet in Example 5-1.
Example 5-1. Creating a multidimensional array
// set array length var arrayLength = 3; // create array var multiArray = new Array(arrayLength); for (var i = 0; i < multiArray.length; i++) { multiArray[i] = new Array(arrayLength); } // add items to starting time assortment index multiArray[0][0] = "apple"; multiArray[0][1] = "banana"; multiArray[0][2] = "cherry"; // second multiArray[1][0] = 2; multiArray[1][1] = 56; multiArray[1][ii] = 83; // third multiArray[two][0] = ['test','again']; multiArray[two][1] = ['Java','script']; multiArray[2][2] = ['read','books']; alarm(multiArray); // printed out in get-go index lodge alert(multiArray[2]); // prints out subarray alert(multiArray[two][ii][0]); // individual item
Discussion
Multidimensional arrays in JavaScript are managed by creating a new array as an element within an existing array. The new array can be created as an Assortment
element, or as an array literal.
In Example five-one, an array, multiArray
, is created as an Array
object with three members. Each of those three elements is too created as Assortment
objects with three members. The assortment information is then set up, with the showtime array member containing cord literals, the second containing number literals, and the third array literals—themselves containing two array members, each with a string literal.
To access the array elements, use the square bracket annotation, with each set of brackets used to address each level of the array. In the post-obit lawmaking, the array contents are printed out via an alert window, subsequently being converted to a string outset, if necessary:
alarm(multiArray[2]); // prints out test,once more,Java,script,read,books alarm(multiArray[ii][2]); // prints out read,books warning(multiArray[2][2][1]); // prints out books
Multidimensional arrays are typically used to concur the data from a table construction, only how the structure is maintained is up to the developer. For example, the developer tin can back up an array structure in which the outer index reflects the columns, and the inner reflects the rows. As an example, Table v-1 shows a uncomplicated 5-column, iii-row tabular array containing a set of numbers.
Table v-ane. Elementary table with five columns and three rows and sample data
45.89 | 4 | 34 | 9998.99 | 56 |
3 | 23 | 99 | 43 | 2 |
1 | 1 | 0 | 43 | 67 |
To create this in JavaScript using a multidimensional array, employ the following lawmaking:
var table = new Array(v); table[0] = [45.89, 4, 34, 9998.99, 56]; // beginning row tabular array[1] = [3, 23, 99, 43, 2]; // second row table[ii] = [1, 1, 0, 43, 67]; // tertiary row
Of course, this doesn't have into account cavalcade and row headers. To add in the headers, merely treat them as array information, making sure to incorporate them into the proper place in the array to reflect the table structure.
Note
In a multideveloper environs, it'south essential that there is understanding among the developers about whether table structure information is stored column-axial or row-centric.
5.iii. Creating a Cord from an Assortment
Problem
You want to create a single string from an array.
Solution
Use the Array
object's congenital-in bring together
method to join the array elements into a cord:
var fruitArray = ['apple tree','peach','lemon','lime']; var resultString = fruitArray.join('-'); // apple tree-peach-lemon-lime
Discussion
The Array bring together
method takes 1 optional parameter, a delimiter used to separate the strings when joined—in this example, the dash (-
). It returns a cord with all of the assortment elements concatenated. If the array contains annihilation other than strings, the values are converted to a string equivalent:
var numberArray = [i,two,iii,4,5]; // array literal containing number elements var resultString = numberArray.join('+'); // returns string with i+2+three+iv+5
If the delimiter parameter isn't provided, a comma is inserted between assortment element values by default:
var numberArray = [i,two,three,4,5]; var resultString = numberArray.bring together(); // returns string with one,2,three,4,v
five.four. Sorting an Assortment
Problem
Y'all desire to sort an assortment.
Solution
Use the Array
object'south sort
method:
var fruitArray = ['strawberry','apple','orange','banana','lime']; alert(fruitArray.sort()); // returns apple,banana,lime,orangish,strawberry
Discussion
The Array
object'southward sort
method sorts the array elements alphabetically if no optional compare function parameter is provided. To facilitate the sort, all data types are converted to their string equivalent before sorting:
var numberArray = [four,13,2,31,5]; warning(numberArray.sort()); // returns thirteen,2,31,4,5
Though the array members in this example are numbers, they're sorted in lexicographical (dictionary) order, not numerically. To do an bodily numeric sort, use a custom sort function:
function compareNumbers(a,b) { render a - b; } var numArray = [13,2,31,4,5]; alert(numArray.sort(compareNumbers)); // prints 2,four,5,13,31
The function subtracts the 2d parameter value from the first, and if the first is less than the second, a negative value is returned; otherwise, the value is positive. If the render value is less than nothing, the sort index for the 2nd parameter is set higher than the first parameter. If the value is greater than goose egg, the sort index for the start parameter is gear up higher than the other. If the value is exactly zero, the sort index for the ii is unchanged.
If the array elements incorporate strings that could be converted to numbers, and then the compareNumbers
sort function still works, as number conversion is automated:
var numberArray=["34","4","5"]; warning(numberArray.sort(compareNumbers)); // prints 4,5,34
The sort
method sorts the elements in an ascending order. If you lot want to practice a reverse sort, use the sort
method to sort the elements, and then use the reverse
method to reverse the assortment member club:
var numberArray = [4,5,1,3,2]; numberArray.sort(); numberArray.reverse(); // array at present has 5,four,3,ii,i
five.v. Shop and Admission Values in Order
Problem
You want to store values in such a mode that you can access the values in the order in which they were stored.
Solution
To store and access values in the society in which they're received, create a FIFO (first-in, kickoff-out) queue. Utilise the JavaScript Array
object push
method to add items to the queue, and shift
to retrieve:
// create new assortment var queue = new Array(); // push on three entries queue.push('first'); queue.button('2nd'); queue.push button('tertiary'); // shift ii entries alert(queue.shift()); // returns offset alert(queue.shift()); // returns second alarm(queue); // returns third
Discussion
A queue is an array of elements that are added 1 at a fourth dimension, and retrieved in a first-in, first-out order (FIFO). Retrieve of a line at the banking company: people go to the end when they go far at the bank, and tellers help those in the forepart of the line, who accept been there the longest.
You lot could emulate this behavior using counter variables to hold the index of the last item added (the end), and the index of the concluding ane retrieved (from the front), but luckily, the JavaScript Array
object provides methods that handle this data for us, and too proceed the array make clean in the process.
The Array push
method creates a new array element and adds information technology to the cease of the array:
queue.push('first');
The array chemical element count increments with each pushed element.
The Array shift
method extracts the array element from the front end of the array, removing it from the assortment, and returning the element:
var elem = queue.shift();
The array element count decreases by one with each shifted element, every bit shift
also modifies the array in addition to returning the item.
five.half dozen. Store and Access Values in Opposite Order
Trouble
You lot want to store values in such a manner that you tin can access the values in reverse order: access the most recently stored value first, then a LIFO (last-in, offset-out) stack.
Solution
To access stored values in reverse order (last item added is accessed starting time), create a LIFO (final-in, commencement-out) stack. Use the JavaScript Array
object'due south push
method to add together items to the stack, and the pop
method to retrieve:
// create new array var queue = new Assortment(); // push button on three entries queue.push('first'); queue.push('second'); queue.push('tertiary'); // popular two entries alert(queue.popular()); // returns third alarm(queue.pop()); // returns 2d alert(queue); // returns first
Discussion
A stack is an array of elements, with each new element added to the top of the stack, and retrieved in a last-in, starting time-out (LIFO) order. Think of a stack of dishes: you add plates to the peak every bit they're washed, and retrieve them from the top when needed. You could employ a variable holding an integer that tracks the end of the array afterwards each addition and retrieval, but JavaScript provides the functionality we need.
The Array push
method creates a new array chemical element and adds information technology to the terminate of the array:
queue.push('first');
The array element count increments with each pushed element.
The Assortment pop
method extracts the array element from the end of the array, removing it from the array, and returning the element:
var elem = queue.pop();
The assortment element count decreases by one with each popped chemical element, as pop
modifies the assortment.
5.7. Create a New Assortment equally a Subset of an Existing Array
Trouble
You desire to create a new array from a segment of an existing assortment. If the array elements are objects, you want to keep both arrays in sync.
Solution
Use the Array
object slice
method to create a new array based on elements within a given range:
var origArray = new Array(iv); origArray[0] = new Array("1","two"); origArray[1] = new Array("three","four"); origArray[2] = new Array("five","half-dozen"); origArray[3] = new Array("7","eight"); // create new assortment using slice var newArray = origArray.slice(ane,3);
Word
The Assortment slice
method is a elementary mode of building a new array from a sequent sequence of elements in another array. The parameters are the start and ending index for the sequence of elements to copy. A negative value for either index indicates that slice
should work from the end of the assortment.
If the copied elements are literal values, such equally strings, numbers, and Booleans, they're copied by value —irresolute the value in the old array has no impact on the same values in the new array, and vice versa.
When objects are copied, though, they're copied by reference , whether they're copied via piece
or by direct variable assignment:
var first = new Array("one","two","iii"); var 2nd = beginning; // copied by reference second[1] = "apple"; // first and second arrays now accept "one","apple tree","three"
The code that follows demonstrates the object syncing when used with slice. A section of ane array is used to create a new array with slice
. The elements in the showtime array are Array
objects. In the code, when the value of one of the objects in the starting time array is changed, the change is reflected in the new array. Conversely, when a value is inverse in the new array, the modify is reflected in the original array:
var origArray = new Assortment(4); origArray[0] = new Array("ane","2"); origArray[1] = new Array("iii","four"); origArray[2] = new Array("five","six"); origArray[3] = new Assortment("seven","eight"); var newArray = origArray.slice(1,3); alert(newArray); // prints out three,four,five,six // modify original origArray[one][0] = "octopus"; // print out new alert(newArray); // prints out octopus,four,five,six // modify new newArray[1][1] = "kitten"; // impress out sometime alert(origArray); // prints out one,two,octopus,four,5,kitten,seven,eight
Another handy use for slice
is to convert the part arguments property into a proper assortment:
var args = Assortment.prototype.slice.call(arguments);
Using piece
to create a subset of an array is a style of quickly copying a subset of an array and, if the values are objects, ensure both arrays are in sync. Be aware, though, that IE8 doesn't support slice
.
5.8. Searching Through an Assortment
Problem
Yous want to search an array for a specific value and get the array element index if found.
Solution
Utilize the new (ECMAScript 5) Array
object methods indexOf
and lastIndexOf
:
var animals = new Array("dog","cat","seal","elephant","walrus","lion"); alert(animals.indexOf("elephant")); // prints 3
Discussion
Though support for both indexOf
and lastIndexOf
has existed in browsers for some time, it'southward only been formalized with the release of ECMAScript 5. Both methods take a search value, which is and then compared to every element in the array. If the value is found, both return an index representing the array element. If the value is non found, –1 is returned. The indexOf
method returns the start i institute, the lastIndexOf
returns the last 1 found:
var animals = new Array("dog","cat","seal","walrus","lion", "cat"); alert(animals.indexOf("true cat")); // prints ane alarm(animals.lastIndexOf("true cat")); // prints 5
Both methods tin take a starting alphabetize, setting where the search is going to start:
var animals = new Array("canis familiaris","cat","seal","walrus","lion", "cat"); alert(animals.indexOf("cat",2)); // prints five alert(animals.lastIndexOf("cat",4)); // prints 1
Currently, all of the book'due south target browsers support indexOf
and lastIndexOf
, except for IE8.
Run across Likewise
Every bit mentioned, non all browsers back up indexof
and lastIndexOf
. A cross-browser method to implement like functionality in these browsers is given in the Mozilla documentation, at https://programmer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Assortment/indexOf. Since IE8 doesn't support indexOf
, here'south the Mozilla workaround for the part:
if (!Array.prototype.indexOf) { Array.paradigm.indexOf = role(elt /*, from*/) { var len = this.length >>> 0; var from = Number(arguments[1]) || 0; from = (from < 0) ? Math.ceil(from) : Math.floor(from); if (from < 0) from += len; for (; from < len; from++) { if (from in this && this[from] === elt) render from; } return -ane; }; }
5.9. Flatten a Multidimensional Array
Problem
You want to flatten a multidimensional array into a single dimensional array.
Solution
Use the Array
object concat
method to merge the array dimensions into a unmarried dimensional assortment:
var origArray = new Assortment(); origArray[0] = new Assortment("i","two"); origArray[1] = new Array("three","four"); origArray[2] = new Array("v","half-dozen"); origArray[3] = new Array("seven","eight"); // flatten array var newArray = origArray[0].concat(origArray[1],origArray[2],origArray[3]); alert(newArray[5]); // prints half-dozen
Discussion
The Array
object concat
method takes one or more arrays, and appends the array elements on to the terminate of the contents of the parent assortment on which the method was called. The merged array is then returned as a new assortment.
One utilise for this type of functionality is to render a single dimensional array made up of elements from a multidimensional array, as shown in the solution.
v.10. Search and Remove or Supercede Assortment Elements
Problem
You want to find occurrences of a given value in an array, and either remove the element or replace with another value.
Solution
Use the Array
methods indexOf
and splice
to find and remove/replace array elements:
var animals = new Array("dog","cat","seal","walrus","lion", "cat"); // remove the chemical element from array animals.splice(animals.indexOf("walrus"),one); // dog,cat,seal,lion,cat // splice in new chemical element animals.splice(animals.lastIndexOf("cat"),ane,"monkey"); // dog,cat,seal,lion,monkey
Give-and-take
The splice
method takes 3 parameters. The commencement parameter is required; information technology's the index where the splicing is to take identify. The other two parameters are optional: the number of elements to remove, and a substitute. If the index is negative, the elements will be spliced from the finish, not from the beginning of the array:
var animals = new Array("cat","walrus","lion", "cat"); // splice in new element animals.splice(-1,1,"monkey"); // cat,walrus,lion,monkey
If the number of elements to splice is not provided, all elements from the index to the end will be removed:
var animals = new Assortment("cat","walrus","panthera leo", "cat"); // remove all elements after second animals.splice(2); // true cat,walrus
The concluding parameter, the replaced value, can exist a gear up of replacement values, separated by commas:
var animals = new Array("cat","walrus","lion", "cat"); // replace second element with two animals.splice(2,one,"zebra","elephant"); // cat,walrus,zebra,elephant,cat
Removing or replacing 1 chemical element is handy, merely beingness able to remove or replace all instances of a particular element is even handier. In Example five-2, an array is created with several elements, including multiple instances of a specific value. The splice
method is then used in a loop to replace all of the elements with this one value with elements with a new value. The splice
method is used again, in a separate loop, to remove the newly spliced elements.
Example 5-2. Using looping and splice to supervene upon and remove elements
<!DOCTYPE html> <head> <championship>Looping and Splicing</title> <meta http-equiv="Content-Type" content="text/html;charset=utf-viii" > <script> var charSets = new Assortment("ab","bb","cd","ab","cc","ab","dd","ab"); // replace element while (charSets.indexOf("ab") != -one) { charSets.splice(charSets.indexOf("ab"),1,"**"); } alert(charSets); // **,bb,cd,**,cc,dd,** // delete new element while(charSets.indexOf("**") != -1) { charSets.splice(charSets.indexOf("**"),1); } alert(charSets); // bb,cd,cc,dd </script> </head> <trunk> </body>
The instance works with all of this book's target browsers except for IE8, which doesn't currently support either indexOf
or splice
.
See As well
Run across Recipe 5.8 for a workaround for indexOf
.
5.11. Applying a Function Against Each Array Chemical element
Trouble
Yous want to apply a function to check an array value, and replace it if it matches a given criterion.
Solution
Use the new ECMAScript 5 Assortment
object forEach
to adhere a callback function to each array chemical element:
var charSets = new Array("ab","bb","cd","ab","cc","ab","dd","ab"); office replaceElement(element,index,assortment) { if (element == "ab") assortment[index] = "**"; } // utilize function to each array chemical element charSets.forEach(replaceElement); warning(charSets); // prints **,bb,cd,**,cc,**,dd,**
Discussion
In the last section, we used a while
loop to traverse an assortment to discover and replace a value, simply how much more helpful is it to employ the forEach
method?
The forEach
method takes one parameter, the function. The function itself has three parameters: the array element, the index of the element, and the array. All three were used in the function, replaceElement
.
First, the element's value is tested to see if information technology matches a given cord, ab
. If matched, the array chemical element'due south index is used to change the array element's value with the replacement string, **
.
Notation
Don't return a value from the function passed to the forEach
method, as the value will be discarded.
Chrome, Firefox, Opera, and Safari support forEach
, merely IE8 does not.
Meet Also
The concept of callback functions is covered in more detail in Chapter 6.
Most modern browsers support forEach
. All the same, for those that don't, you can emulate the forEach
beliefs using the Assortment.epitome
property. Mozilla provides a description about how to emulate forEach
at https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Assortment/forEach. For completeness, I've duplicated the code below. To use, add the code into a library part and make sure it's processed before the forEach
method is needed:
if (!Array.image.forEach) { Assortment.epitome.forEach = role(fun /*, thisp*/) { var len = this.length >>> 0; if (typeof fun != "function") throw new TypeError(); var thisp = arguments[1]; for (var i = 0; i < len; i++) { if (i in this) fun.call(thisp, this[i], i, this); } }; }
5.12. Applying a Function to Every Element in an Assortment and Returning a New Assortment
Trouble
Yous desire to convert an array of decimal numbers into a new array with their hexadecimal equivalents.
Solution
Use the Array
object map
method to create a new array consisting of elements from the quondam array that have been modified via a callback part passed to the map
method:
// function to convert decimal to hexadecimal part convertToHex(chemical element,alphabetize,array) { render chemical element.toString(16); } var decArray = new Array(23, 255, 122, 5, xvi, 99); var hexArray = decArray.map(convertToHex); alert(hexArray); // 17,ff,a,five,10,63
Discussion
Like the forEach
method in Recipe 5.11, the ECMAScript 5 map
method allows the states to attach a callback office that is practical to each array element. Unlike forEach
, though, the map
method results in a new array rather than modifying the original assortment. Therefore, you lot won't render a value when using forEach
, merely you lot must return a value when using map
.
The function that's passed to the map method has iii parameters: the current array element, the index for the array element, and the assortment. The forEach
and map
methods are currently not supported by IE8.
See Likewise
Most mod browsers support the Assortment
object map
method, just to ensure that the functionality is present, you tin use the Array.prototype
property to emulate the method'due south behavior. Run across how at the Mozilla website.
For comprehensiveness, I've included the code for the workaround below. To use, include the code in a library function that is processed before the map
method is needed:
if (!Array.prototype.map) { Assortment.image.map = function(fun /*, thisp*/) { var len = this.length >>> 0; if (typeof fun != "office") throw new TypeError(); var res = new Array(len); var thisp = arguments[one]; for (var i = 0; i < len; i++) { if (i in this) res[i] = fun.call(thisp, this[i], i, this); } render res; }; }
5.13. Creating a Filtered Array
Problem
You lot want to filter chemical element values in an array and assign the results to a new array.
Solution
Use the Array
object filter
method:
function removeChars(element,index,array) { return (chemical element !== "**"); } var charSet = new Array("**","bb","cd","**","cc","**","dd","**"); var newArray = charSet.filter(removeChars); alert(newArray); // bb,cd,cc,dd
Give-and-take
The filter
method is some other ECMAScript five addition, like forEach
and map
, covered in Recipes 5.11 and v.12, respectively. Like them, the method is a manner of applying a callback function to every assortment element.
The role passed as parameter to the filter
method returns a Boolean value, true or imitation, based on some test against the assortment elements. This returned value determines if the array chemical element is added to a new array: it is added if the function returns truthful; otherwise, information technology is non added. In the solution, the character cord "**
" is filtered from the original array when the new assortment is created.
The office has three parameters: the array chemical element, the index for the element, and the array, itself. The filter
method is not supported by IE8.
See Also
Support for filter
is fairly broad, but to ensure access to the functionality, there is a way to emulate the filter method using Array.paradigm
. Mozilla details the approach at https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/filter, but I've copied the technique below. To use, include the function in your code, and run the office before you need to admission the filter
method:
if (!Array.prototype.filter) { Array.epitome.filter = role(fun /*, thisp*/) { var len = this.length >>> 0; if (typeof fun != "part") throw new TypeError(); var res = new Assortment(); var thisp = arguments[i]; for (var i = 0; i < len; i++) { if (i in this) { var val = this[i]; // in case fun mutates this if (fun.phone call(thisp, val, i, this)) res.push(val); } } return res; }; }
5.fourteen. Validating Assortment Contents
Problem
You lot want to ensure that an array meets sure criteria.
Solution
Apply the Assortment
object'southward every
method to check that every chemical element passes a given criteria. For example, the following code checks to ensure that every element in the array is an alphanumeric character:
var elemSet = new Array("**",123,"aaa","abc","-",46,"AAA"); // testing function function textValue (chemical element,alphabetize,assortment) { var textExp = /^[a-zA-Z]+$/; render textExp.test(element); } // run test alert(elemSet.every(textValue)); // faux
Or use the Array
object's some
method to ensure that at least some of the elements pass the criteria. Equally an instance, the following lawmaking checks to ensure that at least some of the assortment elements are alphanumeric strings:
var elemSet = new Array("**",123,"aaa","abc","-",46,"AAA"); // testing function function textValue (element,index,assortment) { var textExp = /^[a-zA-Z]+$/; render textExp.test(element); } // run test alert(elemSet.some(textValue)); // truthful
Discussion
The every
and some Array
object methods are the final of the ECMAScript 5 Array
methods I'll exist roofing in this book. Unlike the Assortment
callback function methods I covered in previous recipes in this affiliate, every
and some
functions do not work against all array elements; they only process every bit many array elements as necessary to fulfill their functionality.
The solution demonstrates that the aforementioned callback office tin can be used for both the every
and the some Array
object methods. The difference is that when using the every
method, as soon as the function returns a false value, the processing is finished, and the method returns false. The some
method, though, will continue to exam against every array element until the callback function returns true. At that time, no other elements are validated, and the method returns true. However, if the callback function tests against all elements, and doesn't render true at any point, the some
method returns false.
Which method to use depends on your needs. If all array elements must meet sure criteria, then use every
; otherwise, use some
.
The callback function takes three parameters: the element, the index for the chemical element, and the array. Neither the some
or every
method are supported past IE8, just they are supported past the other target browsers for this book.
See Also
Nigh modern browsers support every
and some
, but for those browsers that don't (such equally most versions of Internet Explorer), you can emulate the behavior using the Array.prototype
. Mozilla covers how to do this at https://programmer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/some and https://programmer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/every.
For comprehensiveness, I've also included the functionality below. To apply, ensure that the script provided is processed before the methods are needed.
Here's how to emulate some
:
if (!Array.paradigm.some) { Array.epitome.some = office(fun /*, thisp*/) { var i = 0, len = this.length >>> 0; if (typeof fun != "function") throw new TypeError(); var thisp = arguments[one]; for (; i < len; i++) { if (i in this && fun.telephone call(thisp, this[i], i, this)) render truthful; } return false; }; }
Hither'southward how to emulate every
:
if (!Array.paradigm.every) { Array.image.every = function(fun /*, thisp*/) { var len = this.length >>> 0; if (typeof fun != "function") throw new TypeError(); var thisp = arguments[1]; for (var i = 0; i < len; i++) { if (i in this && !fun.phone call(thisp, this[i], i, this)) render false; } return truthful; }; }
5.15. Using an Associative Array to Store Form Element Names and Values
Problem
You desire to store course chemical element names and values, for later validation purposes.
Solution
Use an associative assortment to store the elements, using the element identifiers as array index:
var elemArray = new Object(); // find Object, no Array var elem = document.forms[0].elements[0]; elemArray[elem.id] = elem.value;
Iterate over the array using the for...in
statement:
for (var key in elemArray) { str+=key + "," + elemArray[primal] + " "; }
Discussion
Most JavaScript arrays utilize a numeric index, such as the following:
arr[0] = value;
However, you can create an associative assortment in JavaScript, where the array index tin can be a cord representing a keyword, mapping that cord to a given value. In the solution, the array alphabetize is the identifier given the array element, and the actual assortment value is the form chemical element value.
You can create an associative array, simply y'all're non using the Array
object to practice so. Using the Array
object is risky and actively discouraged—especially if you're using one of the built-in libraries that employ the prototype
aspect for extending objects, every bit people discovered when the popular Prototype.js library was beginning released several years agone.
The before Prototype.js library fabricated an assumption that nearly array employ in JavaScript is numeric index–based, like most of the earlier examples in this chapter. The library extended the Assortment
object functionality via Array.prototype
, based on this assumption. Simply extending Array
objects in this style breaks the for...in
loop functionality used to traverse an associative array created from an Array
object.
It'southward not that Prototype.js was "breaking" JavaScript. The for...in
loop was intended for one purpose: iterating over an object'southward properties, such as existence able to loop through the String
object'south properties, or your ain custom object properties.
When nosotros use an Array
object to create an associative array, what we're actually doing is adding new backdrop to the array object, rather than calculation new assortment elements. You could actually create an associative array with a RegExp
or String
, likewise as an Array
. The reason is that in JavaScript objects are associative arrays. When you lot're adding a new assortment, element
:
obj[propName] = "somevalue";
what you're really doing is adding a new object property:
obj.propName = "somevalue";
To further demonstrate how different the associative assortment is from a numeric-based array, when yous utilize an Array
to create an associative array, you can't access the assortment "elements" by index, and the length property returns zero.
Instead of using an Assortment
object to create the associative array, utilize the JavaScript Object
direct. You go the exact same functionality, but avoid the clashes with libraries that extend the base of operations Assortment
object using epitome
.
Example 5-3 shows a web page. Here, when the grade is submitted, all of the course elements of type text are accessed and stored in an associative assortment. The element IDs are used every bit the array keyword, and the values assigned to the array elements. Once collected, the associative array is passed to another role that could be used to validate the values, but in this case simply creates a string of keyword/value pairs, which is then displayed.
Example 5-three. Demonstrating associative array with course elements
<!DOCTYPE html> <html xmlns="http://world wide web.w3.org/1999/xhtml"> <head> <championship>Associative Array</title> <script type="text/javascript"> //<![CDATA[ // go the form element names and values function getVals() { var elems = certificate.getElementById("picker").elements; var elemArray = new Object(); for (var i = 0; i < elems.length; i++) { if (elems[i].type == "text") elemArray[elems[i].id] = elems[i].value; } checkVals(elemArray); return false; } // check values function checkVals(elemArray) { var str = ""; for (var key in elemArray) { str+=key + "," + elemArray[central] + " "; } document.getElementById("event").innerHTML = str; } //--><!]]> </script> </head> <body> <form id="picker" onsubmit="return getVals()"> <characterization>Value ane:</label> <input blazon="text" id="get-go" /><br /> <characterization>Value 2:</characterization> <input type="text" id="second" /><br /> <label>Value 3:</label> <input type="text" id="third" /><br /> <label>Value 4:</label> <input type="text" id="4" /><br /> <input blazon="submit" value="Validate" /> </form> <div id="event"></div> </body> </html>
In the instance, discover that the array index is formed past the form element's id
. When the array is traversed, the for
loop syntax used is:
for (keyword in array)
This syntax accesses the array index, which is then assigned to the keyword variable that tin be used to access the array value:
for (keyword in array) var a = array[keyword];
Effigy v-ane shows the example later values are typed into the class fields and the form is submitted.
Figure v-1. Demonstration of associative assortment and traversing form elements
This type of keyword/value pairing is normally referred to every bit a hash map or hash tabular array , though the JavaScript functionality isn't a true hash map functionality. The reason why it isn't a truthful hash map is that it doesn't account for the fact that the aforementioned keyword could be used with multiple values, and the JavaScript version but accepts strings equally keywords.
Can I Register A Callback Whenever An Element Is Pushed To An Array,
Source: https://www.oreilly.com/library/view/javascript-cookbook/9781449390211/ch05.html
Posted by: hubbarddirarew.blogspot.com
0 Response to "Can I Register A Callback Whenever An Element Is Pushed To An Array"
Post a Comment