WARNING - Everything except Objects and Arrays are copied by value.
Example of array copy by reference - a potential gotcha:
let things = ["thing1", "thing2"];
let different_things = things;
different_things.push("thing3");
> things
// [ 'thing1', 'thing2', 'thing3' ]
Create a shallow copy of an Object:
let obj = Object(key : "val");
let copy = Object.assign({}, obj);
Create a shallow copy of an Array:
let ar = ["thing1", "thing2"];
let copy = ar.slice();
Objects and Arrays can also be copied by JSONifying them. This produces a deep copy, however there are some caveats.
Functions, for instance, can't be copied this way. Basically anything that can't be represented without finagling in JSON won't work.
let thing = Object();
let copy = JSON.parse(JSON.stringify(thing));
A custom deep copy function might look something like this. Here we use recursion to delve into Objects and Arrays in order to copy their contents by value:
Note that the same caveats as JSONifying an Object apply here, however we can handle them specifically, as we've done here with Dates.
function deepCopy(obj) {
let result = Object();
if (Array.isArray(obj)) {
result = Array();
}
for (let key in obj) {
const prop = obj[key];
if (prop !== null && prop !== undefined && typeof prop === 'object') {
// Handle special types of Objects here:
if (prop.constructor === Date) {
result[key] = new Date(prop.getTime());
} else {
result[key] = deepCopy(prop);
}
} else {
result[key] = prop;
}
}
return result;
}
Ajax, which stands for Asynchronous JavaScript and XML, is an ubiquitous feature of web applications. It allows asynchronous requests to be fired from JavaScript.
Nicely patterned AJAX call using jQuery:
let that = this;
$.ajax({
url : the.server.api,
data : {
"key" : val,
"key2" : val2,
},
type : "GET", // ie. GET, POST
dataType : "json", // If result is NOT of type, throw error
})
.done(function(jqxhr, status, exception) {
// On Success
// data: xhr object
// textStatus : "error"
// xhr: "Internal Server Error"
console.log(jqxhr)
})
.fail(function(jqxhr, status, exception) {
// On Failure
console.error("API request failed with " + jqxhr.status); // ie. 200, 404, 500
})
.always(function(jqxhr, status, exception) {
// Do Always
})
Array Ops at a Glance:
unshift pop
-----> ----->
[0, 1, 2, ..., n-1, n]
<----- <-----
shift push
Both pop()
and shift()
return a single element, AND modify the array:
let l = [0,1,2,3,4];
l.pop()
// 4
l
// [0,1,2,3]
let l = [0,1,2,3,4];
l.shift()
// 0
l
// [1,2,3,4]
Both push()
and unshift()
return the Array's new length
, AND modify the Array:
let l = [0,1,2,3,4];
l.push(5);
// 6
l
// [ 0, 1, 2, 3, 4, 5 ]
l.unshift(6);
// 7
l
// [ 6, 0, 1, 2, 3, 4, 5 ]
Arrays can be concatenated with .concat()
:
[].concat([1,2,3,4,5],[6,7,8])
// [ 1, 2, 3, 4, 5, 6, 7, 8 ]
Find the intersection of two Arrays of primitives:
[1, 2, 3].filter(value => [3, 4, 5].includes(value))
// [3]
Map creates a new array by mapping each element in the original array to an element in the new array via the passed function. We'll use the following list for examples:
let list = [
{name : "name 1", val: 1},
{name : "name 2", val: 2},
{name : "name 3", val: 3},
{name : "name 4", val: 4},
];
Example of map returning a single property from each member function:
list.map(o => o.val);
// [ 1, 2, 3, 4];
Example evaluating Array elements:
list.map(o => o.val > 1);
// [ false, true, true, true]
Example evaluating Array elements with long-form function argument:
list.map(function(o) {
return o.val > 1
});
// [ false, true, true, true]
Reduce reduces an array to a single value. We'll use the following list for examples:
let list = [
{name : "name 1", val: 1},
{name : "name 2", val: 2},
{name : "name 3", val: 3},
{name : "name 4", val: 4},
];
Example reducing an array of integers to their sum:
[1,2,3,4,5].reduce((a,b) => a + b);
// 15
Example reducing an array of strings to their "sum":
["house","by","the","sea"].reduce((a,b) => a + " " + b);
// 'house by the sea'
If we try to do the same thing with elements of different types, the result may be unexpected:
list.reduce((a,b) => a + b.val);
// '[object Object]234'
To do the same thing to objects, we need to also pass a second argument to reduce, the initialValue
:
list.reduce((a,b) => a + b.val, 0);
// 10
Simple filter on an array of objects. This will create a new array with only objects whose val
prop is larger than 6.
let list = [
{name : "name 1", val: 1},
{name : "name 2", val: 2},
{name : "name 3", val: 3},
{name : "name 4", val: 4},
{name : "name 5", val: 5, obj : {obj_val : 1}},
{name : "name 5", val: 5, obj : {obj_val : 2}},
];
list.filter(o => o.val < 3);
// [{name : "name 1", val: 1},{name : "name 2", val: 2}]
Loop shorthand takes two distinct forms, in
and of
. The following examples make use of this Array:
let list = [
{name : "Elephant", size : 15, props : {color: "grey"}},
{name : "Lion", size : 12, props : {color: "gold"}},
{name : "Stork", size : 6, props : {color: "white"}},
{name : "Ardvark", size : 4, props : {color: "brown"}},
];
Use in
to iterate over Array keys:
for (o in list) { console.log(o) };
// 0, 1, 2, 3
Use of
to iterate over Array elements:
for (o of list) { console.log(o.name) };
// Elephant, Lion, Stork, Ardvark
We can also use a slightly longer format, that makes it much clearer what the variable represents:
for (let key in list) {
const item = list[key];
console.log(item.name);
};
// Elephant, Lion, Stork, Ardvark
Time Execution:
var t0 = performance.now();
// Do Something
var t1 = performance.now();
console.log("loadData() selection took " + (t1 - t0) + " milliseconds.")
Find the maximum value from an Array list
of Objects with property val
and return value:
Math.max.apply(Math, list.map(function(o) { return o.val; }))
Produce all combinations of array members:
getCombn(arr, pre) {
pre = pre || '';
if (!arr.length) {
return pre;
}
let that = this;
var ans = arr.reduce(function(ans, value) {
return ans.concat(that.getCombn(arr.slice(1), pre + value));
}, []);
return ans;
}