tags : Programming Languages, Typescript
Data types and values
Values
Primitive(7)

- Immutable
- undefined, number, string, boolean, symbol, bigint are not
objects, they’re primitives. - primitive and variable assigned a primitive value are different
- No methods, no properties: But JS has wrapper around primitives. Eg.
stringprimitive has the ephemeralStringobject wrapper which gives it nice methods likeincludes. Sometimes called the “auto-boxing behavior” - All primitive types, except
nullandundefined, have their correspondingobjectwrapper.
Non-primitive/objects
- Mutable
- Definition:
objectscan be seen as a collection ofproperties/methods objectcan havepropertiesandmethods, none, one or both.- Most things except primitives are objects. Even functions.
More on non-primitive/objects
FAQ on Object & object
-
Using Object as a map
- I used to use
Objectas map/dictionary for storing k-v data. - Not good, because it has all the extra property things that we don’t care about. It’s like taking an airplane to go 2kms. Use
Mapinstead.
- I used to use
-
What about
[object Object]?- String representation when
toString()is used. Object.prototype.toString()returns"[object Type]"Typeis set bySymbol.toStringTag- When
Symbol.toStringTagis unset, it’ll just go[object Object]
- String representation when
object vs Object
object- There’s nothing tangible called
objectin JS. It’s a concept. It’s anything that has properties, it’s anything that’s not a primitive. - Issues w
typeof- One source of confusion is the
typeofoperator. For anything other than a pre-defined list it’ll return “object”. This just signals that it’s some object, something’s that’s not a primitive. (typeofis like a limited best effort thing) - Eg.
typeof new Date()andtypeof nullboth return ‘object’. So for differentiating between subtypes, maybe useinstanceof - So
typeofis good if you just want to work onprimitivevalues.
- One source of confusion is the
- There’s nothing tangible called
Object- JS has many built in
objects,Object(w the capitalO) is one of them. - Other common
objectsare Function, Array, Date, RegExp, Error etc. Objectbehaves the same as{}(Object literal)// object literals are cool const obj = { // __proto__ __proto__: theProtoObj, // Shorthand for 'handler: handler' handler, // Methods toString() { // Super calls return "d " + super.toString(); }, // Computed (dynamic) property names ["prop_" + (() => 42)()]: 42, };- Every
objectin JS is inherited ofObject.prototype
- JS has many built in
Properties
propertyis an association between a name (or key) and a value. When the value of apropertyis afunction, we call it amethod.- Can be “assigned”, or can be set via
attributesusingObject.defineProperty - There are hidden/internal properties, usually represented via
[[. eg.[[Prototype]]. - JS objects have properties. They’re of 2 types.
- Data property: value, writable, enumerable, configurable
- Accessor property: get, set, enumerable, configurable
-
Prototype

prototypeof anobjectis conceptually a hiddenpropertyprototypeof points to anotherobjector tonull- Usually represented using
[[Prototype]], sometimesobj.__proto__but that’s not official. - WATCHOUT:
Functions(constructors) have a.prototypeproperty, that’s different. It specifies what the[[Prototype]]should be for newly created objects using the constructor.
Other stuff
Functions
this
- It has 5 perspective, check javascript garden ref. for solid info
- arrow functions are cool, when using them
thiswill point parent(past hack: bind, self etc.), it does not have its ownthis. So ez.
apply/call/bind
- These help us explicitly set
parametersusingthis - The first
parameterof these functions point to thethisArg(what shouldthispoint to) call- Lets us call some function by explicitly setting
this - Don’t need it usually
- Lets us call some function by explicitly setting
apply- like
callbut lets us pass array of arguments - Earlier we needed to do things like
Math.max.apply(null, nums), now we don’t need it cuz spread operator - Don’t need it usually
- like
bind- Lets us build new functions out of
parameters - Related to the idea of currying
- Lets us build new functions out of
Closures
- A closure is formed by
- Returning from a function from the execution context of a function call and referencing that inner function to a property of another object.
- Directly assigning a reference to such a function object to, for example, a global variable, a property of a globally accessible object or an object passed by reference as an argument to the outer function call.
Promises
- Check the execution order here
- Not to mention, these are
objects catch(failureCallback)is short forthen(null, failureCallback)- If your error handling code is the same for all steps, you can attach
catchit to the end of the chain - The handlers we pass to
.thenand.catchNEED toreturn. Otherwise we end up creating a race condition. - When we do
.then(()=> doSomething())we mean.then((IGNORE_RESULT_HERE)=> doSomething()) - Good habit to always have a
.catch async/awaithelps avoid most of the catches here.Promise.allruns things concurrently(doesn’t check order), We can usereduceto run things sequentially. But make sure you want to run things sequentially. In general if simply chaining with.then, then things will be invoked in order.
Nested or flat?
const listOfIngredients = [];
doSomething()
.then((url) =>
fetch(url)
.then((res) => res.json())
.then((data) => {
listOfIngredients.push(data);
}),
)
.then(() => {
console.log(listOfIngredients);
});
// OR
doSomething()
.then((url) => fetch(url))
.then((res) => res.json())
.then((data) => {
listOfIngredients.push(data);
})
.then(() => {
console.log(listOfIngredients);
});- Simple promise chains are best kept flat without nesting
- nested chains can be useful if you want to scope
catch/ error silencing, eg. do not make failure of some optional chain fail the whole thing.
Mix callbacks and promises?
- Not a good idea to mix callbacks and promises
- Better to just convert the callback thing into a promise.
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
await
- for loop / for-loop and wait
Typed Arrays
const buffer = new ArrayBuffer(16); // just the buffer
const int32View = new Int32Array(buffer); // we add a view to the buffer
const int16View = new Int16Array(buffer); // we add another view to the same buffer!
// data objects containing multiple data types
const buffer = new ArrayBuffer(24);
const idView = new Uint32Array(buffer, 0, 1);
const usernameView = new Uint8Array(buffer, 4, 16);
const amountDueView = new Float32Array(buffer, 20, 1);
- These are very different things technically from
Array - Implementation:
ArrayBuffer+view/context
ArrayBuffer: Just chunks of data, no methods nothing. fixed-length binary data buffer.view/context/Dataview: data type, starting offset, and number of elements etc.
- It’s not accessible directly, instead you use the different
views, examples some predefinedviews.
- If you need custom view, might look at
Dataview, it gives you low level access and can change things like change the byte order.
Random notes
- You can also use the unary plus
+as a shorthand forNumber() ??(Nullish coalasing is cool)- JS now has
?.like Ruby - If you pass any other object to the index signature the JavaScript runtime actually calls .toString on it before getting the result.
Versions
- ES6/ES2015
- ES7/ES2016: array.include, etc
- ES2017
- ES2018
- ES2019
- ES2020
- ES2021
- ES2022