Strings and Arrays
Strings and Arrays
First… a quick note.
- Strings are primitives. They just act like objects when they're called upon to do so
const s = "I'm not really an object"; s.message = "prove it!" console.log(s.message);
- Uh turns out that
Arrays
are actually just objects (they're not a separate type on their own)
Strings
They're pretty unremarkable (whew!) →
- just an ordered sequence of characters
- they're immutable
- a string literal can be constructed with single or double quotes:
'
or"
- backslash escapes the next character (new line, tab, literal backslash, etc.)
- the
.length
property contains the number of characters in a string - you can get a specific character by using the indexing operator: myString[0] …
- (negative indexes don't work, you'll have to use myString.length - 1 for the last index)
Arrays
Arrays
though… are a little strange. First - 2 ways to create an Array:
- literal (square brackets with comma separated values):
[1, 2, 3]
- an empty array is just open and close bracket:
[]
- you can index with brackets, and you can retrieve the number of elements using
.length
- an empty array is just open and close bracket:
- you may see Arrays created with an
Array
constructor- but be careful when using the
Array
constructor!!! - with a single
Number
argument, it creates anArray
of that length - …anything else constructs an Array with the arguments as elements
new Array(2) // an array with two empty elements !?!?!?! new Array('abc') // ['abc'] oookaaaay new Array(2, 4, 6) // [2, 4, 6] sure!
- but be careful when using the
Arrays are What?
Also, Arrays
are actually just objects. This means that their indexes are properties. →
- indexes don't have to be contiguous!?
- you can have holes in your arrays (length counts them as elements, though):
const a = []; a[0] = 'ok' a[4] = 'where are the previous elements?' console.log(a); console.log(a.length);
- generally, avoid doing this… behavior when working with
Array
holes varies depending on what you're doing! - there's actually a section in the book devoted to this
String and Array Methods
Strings are object like when you want them to be, and Arrays are secretly objects. They both have a bunch of built-in methods. →
Some Useful String Methods
Note that these methods don't change the original string that they're called on: →
- split([separator][, limit]) - splits a String object into an array of strings by separating the string into substrings - default is one element of original string if no separator is specified. →
- toUpperCase() and toLowerCase() - um… self explanatory? →
- slice(beginSlice[, endSlice])
- extracts a section of a string and returns a new string starting at index, beginSlice, and going to end of string or up to, but not including endSlice
"racecar".slice(1, 4)
→'ace'
- negative values for both parameters are ok (treated as length + index value):
"racecar".slice(0, -1)
→'raceca'
- extracts a section of a string and returns a new string starting at index, beginSlice, and going to end of string or up to, but not including endSlice
- replace(regexp|substr, newSubStr|function[, flags]) - returns a new string with some or all matches of a pattern replaced by a replacement (both substrings and regexes work) →
Some Useful Array Methods
These methods modify the array that they're called on! →
- pop() - removes and returns the last element from the array
- push(element1, …, elementN) - adds one or more elements to the end of an array and returns the new length of the array
- reverse() - reverses the order of the elements of an array — the first becomes the last, and the last becomes the first.
- sort([compareFunction])
- sorts the elements of an array in place and returns the array (default sort is by unicode code point value)
compareFunction(a, b)
→return
-1
,0
, or1
- splice(index, howMany[, element1[, …[, elementN]]])
- adds and/or removes elements from an array, starting at
index
… and removinghowMany
elements - returns spliced elements as array
- negative
index
- begin that many elements from end
- adds and/or removes elements from an array, starting at
And Even More Array Methods
These don't mutate the array that they're called on. →
- slice(index, howMany[, element1[, …[, elementN]]]) - returns a shallow copy of a portion of an array into a new array object
- called with no arguments - copies entire array (start at index 0, end at last element)
- join([separator = ',']) - joins all elements of an array into a string using separator (default is comma)
- forEach(callback[, thisArg]) - calls a function for each element in the array
- every(callback[, thisArg]) - tests whether all elements in the array pass the test implemented by the provided function
- indexOf(searchElement[, fromIndex=0]) - returns index of searchElement or -1 if not found
Splice
splice
removes elements (in place) from an Array, and optionally inserts elements.
- 1st parameter,
start
specifies the index (inclusive) to start modifying the Array- negative indexes start from left
- indexes greater than last index is set to the last index
- 2nd parameter,
deleteCount
specifies the number of elements to be deleted- omitting this argument will cause all elements after
start
to be removed
- omitting this argument will cause all elements after
Splice Continued
- all arguments after the second parameter are elements that will be added to the original Array
- these elements will be inserted at the
start
specified - if there are no parameters after the second,
splice
will only remove elements
- these elements will be inserted at the
- returns the elements removed as an Array
TL;DR
splice
removes elements from an existing Array- it optionally replaces those elements with other elements
- it gives back the elements that were removed as an Array
Splice Examples
Using the following code, a = [2, 4, 6, 8, 10, 12]
, what is the new content of a… and what is returned… after calling splice (assume a is reset each time)? →
a.splice(2);
a.splice(2, 2);
a.splice(-2);
a.splice(2, 2, 1, 1);
returned: [ 6, 8, 10, 12 ], a: [ 2, 4 ]
returned: [ 6, 8 ], a: [ 2, 4, 10, 12 ]
returned: [ 10, 12 ], a: [ 2, 4, 6, 8 ]
returned: [ 6, 8 ], a: [ 2, 4, 1, 1, 10, 12 ]
Splice vs Slice
They sound the same! They do different stuff though! … totally different stuff.
Think of slice
as a way of copying a sub-Array from an existing an Array.
- parameter 1,
begin
, is the start index (inclusive) of the sub-Array to be copied out- begins at index 0 if it is not specified
- negative starts from end
- parameter 2,
end
, is the end of the sub-Array (exclusive … so goes up to, but does not include)- ends at last index if not specified
- negative starts from end
- think slices in Python lists
- it does not alter the original Array
Slice Examples
What is the output of the following code? →
a = [2, 4, 6, 8];
console.log(a.slice());
console.log(a.slice(1));
console.log(a.slice(1, 3));
console.log(a.slice(-1));
console.log(a);
[ 2, 4, 6, 8 ]
[ 4, 6, 8 ]
[ 4, 6 ]
[ 8 ]
[ 2, 4, 6, 8 ]
Using Slice to Copy
A common way of duplicating an Array is to use slice. →
const a = [1, 2, 3];
const b = a.slice();
a.push(4);
console.log(b);
- er… be careful, though…
- object references are copied which means they'll still refer to the same object
- what is the output of the code below? →
const a = [{}, 2, 3];
const b = a.slice();
b[0].tricky = 'yup, same object';
console.log(a);
[ { tricky: 'yup, same object' }, 2, 3 ]
Spread to Copy
As of ES6, you can also use spread syntax to copy an Array:
const numbers = [1, 2, 3, 4];
const copy = [...numbers]
- in your
Array
literal - add three dots
- followed by the name of the Array you're copying
- only goes one-level deep (shallow)
- note that you can also use this on multiple Arrays (to concatenate):
const words1 = ['foo', 'bar']; const words2 = ['baz', 'qux']; const allWords = [...words1, ...words2]
Um. Again… Numbers, strings and booleans are immutable!
Working With Arrays
Because arrays are mutable, we have to be careful when we work with them.
For example, we can create functions that work on arrays:
- in place (that is, change the elements in the array itself)
- … or return an entirely new array with the elements of the original array changed
(Let's see… →)
Double Values, New Array
Create a function called doubleValues. →
- it should have one parameter, an array called
arr
- it should return an entirely new array, with the elements of the original array doubled
- double each element by multiplying by 2 (regardless of the type)
Double Values, New Array, Implementation
What do you think the following code prints out? →
const numbers = [1, 2, 3];
const doubleValues = function(arr) {
const doubled = [];
for(let i = 0; i < arr.length; i++) {
doubled.push(arr[i] * 2);
}
return doubled;
};
result = doubleValues(numbers);
console.log(numbers);
console.log(result);
[1, 2, 3]
[2, 4, 6]
Double Values, In Place
Create a function called doubleValuesInPlace. →
- it should have one parameter, an array called
arr
- it should double each element in place by multiplying each element by 2 (regardless of the type)
- it does not return a value
Double Values, In Place, Implementation
What do you think the following code prints out? →
const numbers = [1, 2, 3];
const doubleValuesInPlace = function(arr) {
for(let i = 0; i < arr.length; i++) {
arr[i] *= 2;
}
};
const result = doubleValuesInPlace(numbers);
console.log(numbers);
console.log(result);
[2, 4, 6]
undefined