-
-
Save mikaelbr/9900818 to your computer and use it in GitHub Desktop.
// === Arrays | |
var [a, b] = [1, 2]; | |
console.log(a, b); | |
//=> 1 2 | |
// Use from functions, only select from pattern | |
var foo = () => [1, 2, 3]; | |
var [a, b] = foo(); | |
console.log(a, b); | |
// => 1 2 | |
// Omit certain values | |
var [a, , b] = [1, 2, 3]; | |
console.log(a, b); | |
// => 1 3 | |
// Combine with spread/rest operator (accumulates the rest of the values) | |
var [a, ...b] = [1, 2, 3]; | |
console.log(a, b); | |
// => 1 [ 2, 3 ] | |
// Fail-safe. | |
var [, , , a, b] = [1, 2, 3]; | |
console.log(a, b); | |
// => undefined undefined | |
// Swap variables easily without temp | |
var a = 1, b = 2; | |
[b, a] = [a, b]; | |
console.log(a, b); | |
// => 2 1 | |
// Advance deep arrays | |
var [a, [b, [c, d]]] = [1, [2, [[[3, 4], 5], 6]]]; | |
console.log("a:", a, "b:", b, "c:", c, "d:", d); | |
// => a: 1 b: 2 c: [ [ 3, 4 ], 5 ] d: 6 | |
// === Objects | |
var {user: x} = {user: 5}; | |
console.log(x); | |
// => 5 | |
// Fail-safe | |
var {user: x} = {user2: 5}; | |
console.log(x); | |
// => undefined | |
// More values | |
var {prop: x, prop2: y} = {prop: 5, prop2: 10}; | |
console.log(x, y); | |
// => 5 10 | |
// Short-hand syntax | |
var { prop, prop2} = {prop: 5, prop2: 10}; | |
console.log(prop, prop2); | |
// => 5 10 | |
// Equal to: | |
var { prop: prop, prop2: prop2} = {prop: 5, prop2: 10}; | |
console.log(prop, prop2); | |
// => 5 10 | |
// === Potential grammar hiccups | |
// Oops: This doesn't work: | |
var a, b; | |
{ a, b } = {a: 1, b: 2}; | |
// But this does work | |
var a, b; | |
({ a, b } = {a: 1, b: 2}); | |
console.log(a, b); | |
// => 1 2 | |
// This due to the grammar in JS. | |
// Starting with { implies a block scope, not an object literal. | |
// () converts to an expression. | |
// From Harmony Wiki: | |
// Note that object literals cannot appear in | |
// statement positions, so a plain object | |
// destructuring assignment statement | |
// { x } = y must be parenthesized either | |
// as ({ x } = y) or ({ x }) = y. | |
// === Combined destructuring of objects and arrays | |
// Combine objects and arrays | |
var {prop: x, prop2: [, y]} = {prop: 5, prop2: [10, 100]}; | |
console.log(x, y); | |
// => 5 100 | |
// === Nested object destructuring | |
// Deep objects | |
var { | |
prop: x, | |
prop2: { | |
prop2: { | |
nested: [ , , b] | |
} | |
} | |
} = { prop: "Hello", prop2: { prop2: { nested: ["a", "b", "c"]}}}; | |
console.log(x, b); | |
// => Hello c | |
// === Combining all to make fun happen | |
// All well and good, can we do more? Yes! | |
// Using as method parameters | |
var foo = function ({prop: x}) { | |
console.log(x); | |
}; | |
foo({invalid: 1}); | |
foo({prop: 1}); | |
// => undefined | |
// => 1 | |
// === Nested advanced examples | |
// Can also use with the advanced example | |
var foo = function ({ | |
prop: x, | |
prop2: { | |
prop2: { | |
nested: b | |
} | |
} | |
}) { | |
console.log(x, ...b); | |
}; | |
foo({ prop: "Hello", prop2: { prop2: { nested: ["a", "b", "c"]}}}); | |
// => Hello a b c | |
// === In combination with other ES2015 features. | |
// Computed property names | |
const name = 'fieldName'; | |
const computedObject = { [name]: name }; // (where object is { 'fieldName': 'fieldName' }) | |
const { [name]: nameValue } = computedObject; | |
console.log(nameValue) | |
// => fieldName | |
// === Rest and defaults | |
var ajax = function ({ url = "localhost", port: p = 80}, ...data) { | |
console.log("Url:", url, "Port:", p, "Rest:", data); | |
}; | |
ajax({ url: "someHost" }, "additional", "data", "hello"); | |
// => Url: someHost Port: 80 Rest: [ 'additional', 'data', 'hello' ] | |
ajax({ }, "additional", "data", "hello"); | |
// => Url: localhost Port: 80 Rest: [ 'additional', 'data', 'hello' ] | |
ajax({ }); | |
// => Url: localhost Port: 80 Rest: [] | |
// Doesn't work due to trying to destructure undefined | |
ajax(); | |
// => Uncaught TypeError: Cannot match against 'undefined' or 'null' | |
// To fix this we need to have default value for parameter in function | |
// Note: See the `= {}` at the end, saying default empty object if the first argument is undefined. | |
var ajax = ({ url: url = "localhost", port: p = 80} = {}) => { | |
console.log("Url:", url, "Port:", p); | |
}; | |
// Now this works. | |
ajax(); | |
// => Url: localhost Port: 80 | |
ajax({ }); | |
// => Url: localhost Port: 80 | |
ajax({ port: 8080 }); | |
// => Url: localhost Port: 8080 | |
ajax({ url: "someHost", port: 8080 }); | |
// => Url: someHost Port: 8080 | |
// === Similar to _.pluck | |
var users = [ | |
{ user: "Name1" }, | |
{ user: "Name2" }, | |
{ user: "Name2" }, | |
{ user: "Name3" } | |
]; | |
var names = users.map( ({ user }) => user ); | |
console.log(names); | |
// => [ 'Name1', 'Name2', 'Name2', 'Name3' ] | |
// === Usage in for..of loops | |
var users = [ | |
{ user: "Name1" }, | |
{ user: "Name2", age: 2 }, | |
{ user: "Name2" }, | |
{ user: "Name3", age: 4 } | |
]; | |
for (let { user, age = "DEFAULT AGE" } of users) { | |
console.log(user, age); | |
} | |
// => Name1 DEFAULT AGE | |
// => Name2 2 | |
// => Name2 DEFAULT AGE | |
// => Name3 4 |
... Let's simplify the code to see only the relevant parts:
const data = [{ item: 'Awesome shoe' }, { item: 'Fave shirt' }]; const [ { item } ] = data; console.log(item); //=> Awesome shoeAnd that again is pretty much the same as:
const data = [1, 2]; const [ item ] = data; console.log(item); //=> 1And hopefully it's easier to see what is going on. We're destructuring an array and fetching the first element and ignore all other in the array. As if we did
const [ item, ]
.
@mikaelbr - Very helpful, great explanation. Thank you!!!
@mikaelbr, thanks, this is fantastic... ...but I have a question. I will keep it as brief as possible, so there will be a lot of ...
- JS running in a web page reads a JSON file and uses JSON.parse(fileContent).
- Some of the JSON strings in the file can contain special sequences, e.g., \n or \t.
- When these are read in, they are preserved, right up until I pass the JSON to a class constructor and use destructuring to assign values to variables local to the object:
// ...
// myFileContents contains ..."firstArg": "split\nline",...
const myJSON = JSON.parse(myFileContents);
class myClassDoesSomeStuff {
constructor (someArgs = {}) {
const {
firstArg = '',
secondArg = '',
// etc.
...
} = someArgs;
console.log(firstArg)
// ...
let someObject = new myClassDoesSomeStuff(myJSON);
firstArg is printed as
split
line
not as
split\nline
to get around this, I end up doing
let realFirst = JSON.stringify(firstArg).replace(/^""|""$/g, '"');
But that feels really gross, an ugly hack (but neither rude nor evil, so I can live with).
Is there a more elegant solution?
Thanks!
I realized there is an error in my "sample code", the use of console.log, which will print out the newline no matter what:
console.log(firstArg)
In my actual code, values like firstArg are being assigned to a DOM element (a text input box). Without my stringify...replace trick, the \n gets converted, but with it, it is preserved, which is what I want. Sorry for the confusion.
Hi, @PeterWhittaker! I don't know if I understand your problem correctly, but when you have a newline character like this, console.log
will output it with a line break in the console of your developer tool (as you said in your second comment). But when outputting in for instance DOM you won't get two lines in your HTML output. This is as HTML is not whitespace significant (for the most part**), but if you where to inspect the element tree using your developer tool you would see an actual new line in the source code. So the newline is there, but it isn't for instance a <br>
which would cause the browser to render an actual new line.
But in input textarea (note <textarea>
. not <input>
as this is single line) you would have new lines. With a regular <input>
field I belive you would just not see the newline.
Again, I don't really understand your problem. But if you wanted to keep the actual newline character inside your input field, without using textarea. You would have to "escape it". By escaping \n
you would get \\n
which is not a special character but a literal text representation of newline. To escape you can do a regex replace as you've shown, but there is no need for serializing through JSON. Google "escaping newline javascript" and you'll get tons of info and insight.
Read the last part of my comment above on escaping. If you want to keep \n
as just literal text, you escape the new line character. Read this for instance: https://stackoverflow.com/questions/25921319/escape-new-lines-with-js
Thank You!
I was looking for a way to do this but it wasn't obvious to me that this particular approach would actually work: