Objects
Essential
object - is a collection of key-value pairs
- variable with an object only contains a pointer to this object. therefore two objects are only equal when they are the same object
key - unique identifier for one property value
- allowed names: strings (including keywords) and numbers (including float, e and other numeral systems). negative numbers are not allowed
- all key names are being converted to string
- order: integer properties are sorted, others appear in creation order
object initializer - syntax for creating an object using a set of key-value pairs enclosed in curly braces
- also known as object literal
method - function, which is stored in object, as value of object property
- ways to create method:
- method: function() {...} - basic method
- method: () => {...} - arrow function method
- method() {...} - similar conception to shorthand syntax. this is analog of first variant
- method - object shorthand syntax. function is stored in "method" variable
object shorthand syntax - syntax which allows omitting key, if it's value is same as variable name
- e.g. { name } - equals { name: name }
property accessor - term used for syntax, which allows accessing an object property. there are 2 variants of property accessors
- dot notation - accessing with dot. e.g. object.key
- square bracket notation - special syntax for accessing properties dynamically. e.g. object[key] - key is variable with some value
- square bracket notation can also be used for property creation. it allows the following use-cases:
- [x]: y - create computed property. key name is taken from "y" variable
- ['property one']: x - create multiword property
- ['ab' + x]: y - obtain the property name as the result of an expression
accessor property - special type of object property, which looks like property, but internally behaves like method. see Getter & Setter
optional chaining - syntax, which allows accessing deeply nested properties without worrying whether the property exists or not
- e.g. someObject.noSuchProperty?.foo?.bar - returns undefined
- users?.[0] - optional chaining for properties which can contain array
- accessing non-existing property at most data types doesn't trigger error, unless it's function call. accessing at undefined and null triggers error:
- null.fooProperty -> TypeError: Cannot read properties of null
- true.fooProperty === undefined
- true.barMethod() -> TypeError: true.barMethod is not a function
collection - data structure designed for organizing and managing group of related data
- collection might is not always iterable. e.g. it includes simple object
indexed collection - collection of elements, which are stored at ordered numeric indices. this includes arrays and array-like constructs, e.g. NodeList
- indexed collection is always an iterable object
- length - named property, which contains amount of elements in indexed collection
- named property - property which is present within an indexed collection, but its key is not a numeric index
Constructor
new Object() - create new object
- const object = {} - more common and easy way of object creation. it is analog of const object = new Object()
- curly braces don't create scope in this case. so "this" is taken from outside
Static Methods
Object.keys(object) - returns array of own keys
- tricks:
- Object.keys(object).length - check whether object is empty
- Object.keys(object).find(key => object[key] === value) - get the key knowing the value
Object.values(object) - returns array of own values
Object.entries(object) - returns array of entries (array of arrays)
- entries - are arrays, each with key-value pair
Object.fromEntries(iterable) - receives entries as argument and converts it into an object
Object.is(value1, value2) - check whether two values are equal
- it is not equivalent neither to "==" nor to "===" comparison
- "is" does shallow comparison
Object.freeze() - prevent data mutation
Object.hasOwn(object, property) - this is static equivalent of hasOwnProperty method
Object.assign(target, source, sourceN?) - is used to join two or more objects into one. returns updated target
- target - object properties of which will be extended with "source" properties
- if the receiving object already has property named the same, it will be overwritten
- e.g.
- const clone = Object.assign({}, user) - clone an object
- const clone = { ...user } - spread operator provides a new handy way of cloning
Instance Methods
hasOwnProperty(key) - checks whether object contains a property, but excludes inherited properties
- ways of property existence check, considering inherited properties:
- obj[key] === undefined - simple comparison with undefined. accessing a non-existing property results in undefined
- 'fooKey' in barObject - "in" operator results in boolean
toString() - returns string representation of an object
- object might contain custom toString method, which implements custom type conversion logic
valueOf() - converts "this" value to an object
- object might contain custom toValue method, which implements custom type conversion logic
Destructuring
destructuring - makes it possible to unpack properties from objects, or values from arrays, into distinct variables
Object
const { id, name } = user - destructuring object during assignment. this saves "id" and "name" properties into "id" and "name" variables
- inherited properties are also considered
const UserComponent = ({ id, name }) => {...} - dectructuring object passed as function parameter
for (let { id, name } of usersArray) {...} - destructuring object within loop
{ post: { title, body, user, comments } } - accessing nested properties
- in case post is undefined, error will be thrown
{ post: { title: heading } } - giving new names to variables. in such case original name (title) is not accessible
{ operations: [operation] = [{}] } - setting default value for object property
Array
const [foo] = array - destructuring array during assignment. this assigns array's first element to foo
- besides, same use-cases as for objects are possible for arrays
[ , , foo] - in case some element should be skipped, simple coma can be used. in this case foo takes value of array's third element
Spread & Rest
Spread
spread operator - converts array, object or string into distinct values
- other types can not be spread, but spreading them doesn't trigger an error
- tricks:
- const thisArray = […thatArray] - clone an array
- const array = [...string] - string to array. analog of split('')
- const foo = { ...bar, name: 'Bob' } - change an object without mutation
const numbers = [10, 11, 12];
Math.max(…numbers);
Rest
rest operator - converts distinct values into an array or object
- e.g.
- const foo = (…args) => {...} - collect all arguments into args array
- const foo = (bar, ...args) => {...} - save first argument separately and collect all others into args array
- const [foo, ...other] = array - rest into array in pair with destructuring
- rest into object is only possible in pair with destructuring
- e.g. const Bar = ({ children, ...props }) => {...} - children property is saved to variable, all other properties are collected into props object
- tricks:
- const newArray = array.map(({ foo, bar, …keepProperties }) => keepProperties) - delete properties from array of objects
JSON
JavaScript Object Notation (JSON) - text-based format for representing JavaScript objects
- JSON objects are used for data exchange
JSON.stringify(value, replacer, space) - transform object to string
- tricks:
- <pre>{JSON.stringify(state, null, 2)}</pre> - data object visualization
JSON.parse() - transform string to object
- tricks:
- JSON.parse(JSON.stringify(object)) - deep clone an object, final values of which are simple not functions
Getter & Setter
getter - allows calling a function, when object property is accessed, which return property value. such property can be called a calculating property
- function doesn't take any arguments
- advantage of such approach is that function can have access to its object via "this"
- when used without setter, getter function is still called on property accessing
- new value can't be assigned, assignment is ignored without an error
setter - allows calling a function, when new value is assigned to object property
- function takes assignment value as argument
- when used without getter, setter function is still called on assignment, but accessing the property results in undefined
const user = {
firstName: 'Bill',
lastName: 'Gates',
get fullName() {
return `${this.firstName} ${this.lastName}`;
},
set fullName(value) {
const [firstName, lastName] = value.split(' ');
this.firstName = firstName;
this.lastName = lastName;
},
};
user.fullName = 'Steve Jobs';
console.log(user.fullName);
in other words, both getter and setter allow property to look like simple property, but behave similar to a method
Set & Map
keyed collection - alternative to arrays and objects introduced with ES6. it includes Set, Map, WeakSet, WeakMap
- keyed collection is iterable, since it is indexed
- iteration over keyed collection happens in the insertion order. keyed collection can't be reordered
- index can't be used to access element within a set or property within a map
Set
set - a collection of unique values without keys
- uniqueness is set's main feature. repeated adding of same element into the set is just ignored
- benefit over array is that element can be accessed by value easily
- WeakSet - collection of unique values, all of which must be objects
new Set(iterable?) - create Set
- e.g. const set = new Set([1, 5, 10])
- tricks:
- [...new Set(array)] - create array without repetitions
add(value) - adds a value and returns the updated set
delete(value) - removes value and returns boolean. true is value existed, otherwise false
has(value) - returns boolean
clear() - removes everything
size - contains elements count
Map
map - is a collection of key-value pairs. compared to regular object, map is allowed to have keys of any type
- value under each index is object with "key" and "value" properties
- benefit over regular object is that map is iterable
- also map fully preserves the order of insertion, unlike a regular object
- WeakMap - is a collection of key-value pairs whose keys must be objects
new Map(iterable?) - creates the map
- iterable - is any iterable object, which will be converted to the map
- tricks:
- new Map(Object.entries(object)) - convert Object to Map
- Object.fromEntries(map) - convert Map to Object
const recipeMap = new Map([
['feta', 40],
['mustard', 40],
['olive oil', 10]
]);
set(key, value)
- every "set" call returns the map itself, so calls can be chained
get(key)
- returns undefined if key doesn't exist
has(key) - returns boolean
delete(key)
clear() - removes everything from the map
size - contains element count
keys() – returns MapIterator for keys
values() – returns MapIterator for values
entries() – returns MapIterator for entries. it's used under the hood for map iteration
- for (let entry of recipeMap) {...} - equals for (let entry of recipeMap.entries()) {...}
Global Object
global object - is an object that is accessible throughout the entire runtime environment
- see Global Functions for common global methods
window - in browser
global - in Node.js
self - in web workers
globalThis - always refers to the global object, no matter where the code is being executed
- ES2020 feature