mogoz

Javascript

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. string primitive has the ephemeral String object wrapper which gives it nice methods like includes. Sometimes called the “auto-boxing behavior”
  • All primitive types, except null and undefined, have their corresponding object wrapper.

Non-primitive/objects

  • Mutable
  • Definition: objects can be seen as a collection of properties/methods
  • object can have properties and methods, 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 Object as 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 Map instead.
  • What about [object Object]?

    • String representation when toString() is used.
    • Object.prototype.toString() returns "[object Type]"
    • Type is set by Symbol.toStringTag
    • When Symbol.toStringTag is unset, it’ll just go [object Object]

object vs Object

  • object
    • There’s nothing tangible called object in 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 typeof operator. 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. (typeof is like a limited best effort thing)
      • Eg. typeof new Date() and typeof null both return ‘object’. So for differentiating between subtypes, maybe use instanceof
      • So typeof is good if you just want to work on primitive values.
  • Object
    • JS has many built in objects, Object (w the capital O) is one of them.
    • Other common objects are Function, Array, Date, RegExp, Error etc.
    • Object behaves 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 object in JS is inherited of Object.prototype

Properties

  • property is an association between a name (or key) and a value. When the value of a property is a function, we call it a method.
  • Can be “assigned”, or can be set via attributes using Object.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

    • prototype of an object is conceptually a hidden property
    • prototype of points to another object or to null
    • Usually represented using [[Prototype]], sometimes obj.__proto__ but that’s not official.
    • WATCHOUT: Functions (constructors) have a .prototype property, 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 this will point parent(past hack: bind, self etc.), it does not have its own this. So ez.

apply/call/bind

  • These help us explicitly set parameters using this
  • The first parameter of these functions point to the thisArg (what should this point to)
  • call
    • Lets us call some function by explicitly setting this
    • Don’t need it usually
  • apply
    • like call but 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
  • bind
    • Lets us build new functions out of parameters
    • Related to the idea of currying

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 orderexternal link here
  • Not to mention, these are objects
  • catch(failureCallback) is short for then(null, failureCallback)
  • If your error handling code is the same for all steps, you can attach catch it to the end of the chain
  • The handlers we pass to .then and .catch NEED to return. 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/await helps avoid most of the catches here.
  • Promise.all runs things concurrently(doesn’t check order), We can use reduce to run things sequentiallyexternal link . 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

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 directlyexternal link , instead you use the different views, examples some predefined views.
  • 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 for Number()
  • ?? (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