JavaScript - Tips
29 Jun 2017- (how to) merge objects
- (how to) pass class prototype methods as arguments
- (how to) print form data (multipart/form-data)
- (how to) post form data (application/x-www-form-urlencoded)
- [ES6] (how to) get subset of object properties
- [ES6] (how to) remove object property
- [ES6] (how to) create empty array of N elements
- (how to) create array with the same element repeated multiple times
- [ES6] (how to) conditionally add property to object
- [ES6] (how to) remove duplicate values from array
- (how to) flatten array
- (how to) wrap a long template literal to multiline
- [ES6] (how to) export and import
(how to) merge objects
-
using
Object.assign
Object.assign({a: 1, b: 2}, {b: 3}) // {a: 1, b: 3}
-
[ES6] using spread operator (
...
){...{a: 1, b: 2}, ...{b: 3}} // {a: 1, b: 3}
while
Object.assign
modifies target object using spread syntax creates new object.
(how to) pass class prototype methods as arguments
- https://stackoverflow.com/questions/35814872/es6-class-pass-function-as-parameter
- https://stackoverflow.com/questions/35446486/binding-a-function-passed-to-a-component
if it’s necessary to keep current context (say, class method uses instance properties of current class) there are 2 options:
-
pass prototype method and bind it to current context in-place
class Foo { constructor (bar) { this.bar = 123; } foo (userId) { Api.get(userId, this.handleResponse.bind(this)); } handleResponse (response) { return response.baz + this.bar; } }
also it’s possible to do it in constructor once and for all (I haven’t tested this solution):
class Foo { constructor (bar) { this.bar = 123; this.handleResponse = this.handleResponse.bind(this); } foo (userId) { Api.get(userId, this.handleResponse); } handleResponse (response) { return response.baz + this.bar; } }
-
[RECOMMENDED] use field declaration to define prototype method as arrow function
class Foo { constructor (bar) { this.bar = 123; } foo (userId) { Api.get(userId, this.handleResponse); } handleResponse = (response) => { return response.baz + this.bar; } }
now
handleResponse
is bound toFoo
class instance forever (it’s even impossible to rebind it explicitly usingbind
).
(how to) print form data (multipart/form-data)
console.log('formData: ' + JSON.stringify(formData));
(how to) post form data (application/x-www-form-urlencoded)
const jsonToFormData = (json) => {
return Object.entries(json)
.map(entry => {
const [key, value] = entry;
const encodedKey = encodeURIComponent(key);
const encodedValue = encodeURIComponent(value);
return `${encodedKey}=${encodedValue}`;
}, [])
.join('&');
}
const response = fetch(url, {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: jsonToFormData(json)
})
[ES6] (how to) get subset of object properties
const object = {a: 5, b: 6, c: 7};
const picked = (({a, c}) => ({a, c}))(object);
console.log(picked); // {a: 5, c: 7}
or else remove unnecessary properties (see the next tip).
[ES6] (how to) remove object property
to remove static property:
const object = {a: 5, b: 6, c: 7};
const {b, ...rest} = object;
console.log(rest); // {a: 5, c: 7}
to remove calculated property (say, ID):
const object = {1: 'foo', 2: 'bar', 3: 'baz'};
const id = 2;
const {[id]: _value, ...rest} = object;
console.log(rest); // {1: "foo", 3: "baz"}
[ES6] (how to) create empty array of N elements
[...Array(100)]
(how to) create array with the same element repeated multiple times
> Array(7).fill(false)
< [false, false, false, false, false, false, false]
[ES6] (how to) conditionally add property to object
const foo = 1;
const bar = {
...!!foo ? {foo} : null,
baz: 2,
};
NOTE: don’t use ...!!foo && {foo}
because RN JS server might
complain about some performance optimizations if something
else but false
or undefined
is expanded inside object.
[ES6] (how to) remove duplicate values from array
Array.from(new Set([1, 2, 3, 2, 2, 3, 1]))
// => [1, 2, 3]
// or
[...new Set([1, 2, 3, 2, 2, 3, 1])]
// => [1, 2, 3]
NOTE:
- insertion order is preserved
- all duplicate values but the 1st one are removed
(how to) flatten array
const array = [1, [2, 3], 4];
[].concat(...array);
// => [1, 2, 3, 4]
(how to) wrap a long template literal to multiline
<Checkbox
checkedHint={
`foo${gc.NBSP}bar ` +
`baz${gc.NBSP}qux`
}
/>
using line continuation at the point of newline in the literal preserves all spaces at the beginning of the next line:
const variable =
`foo${gc.NBSP}bar \
baz${gc.NBSP}qux`; // leading spaces are preserved
[ES6] (how to) export and import
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export
- https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/import
-
named export
//--------------------------------------------------------- // export.js //--------------------------------------------------------- export const foo = 1; export const bar = 2; // same as above: const foo = 1; const bar = 2; export {foo, bar}; // or mix both variants: export const foo = 1; const bar = 2; export {bar}; //--------------------------------------------------------- // import.js // named exports are imported as a single object //--------------------------------------------------------- // import selected exports using destructuring import {foo, bar} from '.export'; // import all exports import * as baz from '.export';
-
default export
//--------------------------------------------------------- // export.js //--------------------------------------------------------- const foo = 1; const bar = 2; export default {foo, bar}; //--------------------------------------------------------- // import.js //--------------------------------------------------------- import baz from '.export';
NOTE
it’s not possible to use
var
,let
orconst
withexport default
: if it’s still necessary to use default export with, say, a constant, declare and export it in a separate statements:// not allowed: //export default const foo = 123; const foo = 123; export default foo;