Skip to content

Instantly share code, notes, and snippets.

@dominikkaegi
Last active February 14, 2020 22:36
Show Gist options
  • Select an option

  • Save dominikkaegi/4a48d21828bc793fb5242396924a2e67 to your computer and use it in GitHub Desktop.

Select an option

Save dominikkaegi/4a48d21828bc793fb5242396924a2e67 to your computer and use it in GitHub Desktop.
An overview of destructing objects and arrays
// -----------------------------------------------------
// --------------- DESTRUCTERING ---------------
// -----------------------------------------------------
// ------- NON-NESTED ARRAYS ---------------
// Simple Destructering
function foo() {
return [1, 2, 3]
}
var [
a,
b,
c,
..rest
] = foo() || []
// a = 1, b = 2, c = 4, rest = []
// Destructering with Default Types
var [
a,
b = 42,
c,
...rest
] = [1, , 3, 4, 5, , 7]
// a = 1, b = 42, c = 3, rest = [4, 5, undefined, 7]
// The Destructering has nothing to do with declaration. If we have 'a, b, c and rest' already declared somewhere
// in our code we could neglect the var in front of the Destructering patter
var a, b, c, rest;
[
a,
b,
c,
...rest
] = [1, 2, 3, 4, 5]
// a = 1, b = 2, c = 3, rest = [4, 5]
// The only constraint there is for destructering, that they need to be a valid left hand side
// of an asignedment. We could forexample directly add them as a property to an object.
var obj = {}
[
obj.a,
obj.b,
obj.c,
...obj.rest
] = [1, 2, 3, 4, 5]
// obj is now filled up with following properties
// {
// a: 1,
// b: 2,
// c: 3,
// rest: [
// 4,
// 5
// ]
// }
// Swaping Values
var x = 10, y =20
[x, y] = [y, x]
// x = 20, y = 10
// "Throwing away the first value of an array and adding one at the end"
var a = [1, 2, 3]
var x
[x, x, ...a] = [ 0, ...a, 4]
// a = [2, 3, 4]
// But you don't even need an x for this, as array destructering allow you an empty slots
var a = [1, 2, 3]
[, , ...a] = [ 0, ...a, 4]
// ---------- NESTED ARRAYS -------
var a, b, c, rest
[
a,
b,
c,
...rest
] = [1, 2, 3, [4,5,6]]
// a = 1, b = 2, c = 3, rest = [ [4, 5, 6] ]
var a, b, c, rest
[
a,
b,
c,
[
d,
..rest
]
] = [1, 2, 3, [4,5,6]]
// a = 1, b = 2, c = 3, d = 4, rest = [5, 6]
// ----- RESULT OF A DESTRUCTERING PATTER ----------
// The return value of a destructering pattern is always the object / array which has been destructered
// This can be confusing, as one could think that the return value is an array of the destructered values, because
// [a, b] seems to be an array, but it is not an array, it is a pattern on how to break down an array.
function foo() {
return [1, 2, 3, [4,5,6] ]
}
var a, b
var x = [a, b] = foo()
// x = [1, 2, 3, [4,5,6] ]
// The destructering assignement is not creating a new sub array of two items. It is breaking down the array
// according to a pattern
// Because a destructering assignement is returning the object / array itself, you can also
// chain multiple destructering assignment
function foo() {
return [1, 2, 3, [4,5,6] ]
}
var a, b, c, d, rest
[ , , , [ c, d] ] = [ a, b, ..rest] = foo()
// a = 1, b = 2, rest = [3, [4, 5, 6]]
// c = 4, d = 5
// -----------------------------------------------------
// --------------- OBJECT DESTRUCTERING ---------------
// -----------------------------------------------------
// First Level Destructering
function foo() {
return { a: 1, b: 2, c: 3, d: 4}
}
var {
a = 10, // default value 10
b: X = 20, // rename source b to X with default value 10
c: c, // assign property c to c
d, // shorthand if name stays the same
e // will declare variable e with value undefined
} = foo() || {}
// Nested Destructering
function foo() {
return {
a: 1,
b: 2,
c: 3,
d: {
e: 4
}
}
}
var {
a,
d: X,
d: {
e
} = {}
} = foo() || {}
console.log(e)
// Nested Destructering on "undefined properties"
// Nested Destructering with nested objects with defaults to prevent
// hard fails. Recommendation from Getify is to always add a default
// when having nested destructering of properties.
function foo() {
return {
a: 1,
b: 2,
c: 3,
d: {
e: 4
}
}
}
var {
a,
d: X,
d: {
e: {
f: {
g: {
h = 20
} = {}
} = {}
}
} = {}
} = foo() || {}
console.log(e) // undefined
console.log(f) // undefined
console.log(g) // undefined
console.log(h) // 20
// Object Destructering when variables are already defined
// is possible but you need to wrap the whole deconstructiong
// into () braces, because {} are not valid syntax to start with
// as the engine believes it is a scope as opposed to the
// deconstruction properties we want.
function foo() {
return { a: 1, b: 2, c: 3}
}
var a, b, c
({
a,
b,
c
} = foo() || {})
// -----------------------------------------------------
// ------------- PARAMETER DESTRUCTERING -------------
// -----------------------------------------------------
function foo( [a,b,c] = []) {
console.log(a, b, c)
}
foo( [1,2,3] )
// Object Deconstruction allows to mimic named arguments
function foo( {a, b, c}) {
console.log(a, b, c)
}
foo({
a: 1,
b: 2,
c: 3
})
// This allows for easier apis for function with multipe parameter
function foo( {a, b = 20, c} = {}) {
console.log(a, b, c)
}
foo({
c: 3,
a: 1
})
// -----------------------------------------------------
// -------- USING DESTRUCTERING TO MIX OBJECTS --------
// -----------------------------------------------------
// To Mix two objects like defaults and config we needed some utility library
// in the past. Now we can do it with deconstruction
var defaults = {
method: "POST",
callback: function () {},
headers: {
"content-type": "text/plain"
}
}
var config = {
url: 'http://some.url',
callback: foo,
headers: {
"x-requested-with": "foo"
}
}
// Mix the two objects
{ // creating a scope to noe pollute the other space with variables
// deconstructering all the variables we need to create the object
let {
method = defaults.method,
url,
callback = defaults.callback,
headers: {
"content-type": contentType = defaults.headers["content-type"],
"x-requested-with": xRequestedWith
}
} = config
// "reconstructing" the objects with all the extracted variables
config = {
method,
url,
callback,
headers: {
"content-type": contentType,
"x-requested-with": xRequestedWith
}
}
// This has the benefit that we are entirely in controll of how the object get's mixed
// and don't need to rely on some external algorithm.
}
{
// If we would take the above example one step further we would not need a defaults object
// anymore and just add the defaults to the deconstruction:
let {
method = "POST",
url,
callback = function() {},
headers: {
"content-type": contentType = defaults.headers["content-type"],
"x-requested-with": xRequestedWith
}
} =
config = {
method,
url,
callback,
headers: {
"content-type": contentType,
"x-requested-with": xRequestedWith
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment