DEV Community

Cover image for Reading JavaScript guide on MDN (study notes)
Sarah Eisa
Sarah Eisa

Posted on • Edited on

Reading JavaScript guide on MDN (study notes)

I'm relearning JS by reading MDN's JS guide.

I’m doing so as a try to understand the weird stuff in JS cause there must be an explanation right?

This is more like personal notes but maybe it would be helpful to anyone else:)

💡 This may or may not be updated everyday

Grammar and types

  • There's a third type of comments "Hashbang" comments

    #!/usr/bin/env node
    

    it specifies the path to a specific JavaScript interpreter that you want to use to execute the script

    It acts the same as single-line comments // but

    it must be at the beginning of a file

    it can't have any whitespace before

  • you can use letters like å, ü (I mean they never said you can't but still I was like Woah when it run without errors)

    it's because JS uses the Unicode character set

  • let vars are hoisted but not initialized unlike var

    they are considered to be in a "temporal dead zone"

    console.log('The value of b is ' + b); // The value of b is undefined
    var b;
    
    console.log('The value of y is ' + y); // Uncaught ReferenceError: y is not defined
    let y;
    
  • The undefined value converts to NaN when used in numeric contexts

  • null value behaves as 0 in numeric contexts and as false in boolean contexts

  • function expression is not hoisted

    baz(); // TypeError: baz is not a function
    console.log(baz) // undefined
    var baz = function() {
      console.log('bar2');
    };
    
  • Only with the + operator JavaScript converts numeric values to strings

    In case of + and the expression involving strings both sides are converted to string and concatenation is performed

    in case of any other operation it tries to convert both sides to numbers if it's okay then the operation is performed if not NaN is returned

    x = 'The answer is ' + 42 // "The answer is 42"
    x = 'The answer is ' - 42 // NaN
    x = '45' - '3'  // 42
    x = '45' + '3' // 453
    
  • you can create functions and dynamic named properties inside objects

    var obj = {
        toString() {
         // Super calls
         return 'd ' + super.toString();
        },
        // Computed (dynamic) property names
        [ 'prop_' + (() => 42)() ]: 42
    };
    

Loops and iteration

  • Starting from es6 JS has block scope (for, if, while)
  • JS labels used with break and continue to take effect on any block in the hierarchy

    for example if you have a loop and another inside of it you can use the label to break from the loop inside the the second loop

    for (let i = 0; i < 5; i++) {
      console.log("i", i);
      for (let j = 5; j > 0; j--) {
        if (i === j) break; // breaks only from the second for and continues the loop
      }
    }
    
    loop1: for (let i = 0; i < 5; i++) {
      console.log("i", i);
      for (let j = 5; j > 0; j--) {
        if (i === j) break loop1; // breaks from both loops
      }
    }
    
  • Can you use labeled statement to break from forEach loops? No by experiment!

  • for ... of → iterate over iterable objects values (Map, Set, Array)

  • for ... in → iterate over enumerable property keys of an object


Fun Fun Functions

  • function hoisting only works with function declarations not with function expression or arrow function
  • A function can call itself using arguments.callee() nice to know but don't use it
  • When you have a function with an inner function that inner function forms closure which means it can access all the variables defined in the outer function

    The inner function has a reference to the args in the outer function and the reference is preserved until the inner function is no longer accessible

  • The arguments object it's an array-like not an array it only has length property and numbered index

  • an arrow function doesn't have its own this, super, or arguments

  • use Number.isNaN() instead of isNaN cause isNaN is weird and you know it

  • the only difference between encodeURI and encodeURIComponent is

    encodeURI ignores protocol and domain name

    encodeURIComponent encodes everything the whole string


Expressions and operators

  • + true returns 1
  • >> shifts bits to the right
  • >>> shifts bits to the right and adds zeros at the left instead of the shifted bits
  • In bitwise operations the operands are converted to 32bits binary representation
  • && and || returns one of the expression values
  • Use nullish operator ?? Instead of || in case of 0 and ‘’ are valid values
  • typeof null // returns object!!!!!!
  • void operator evaluates an expression then returns undefined

    It can be used with functions that don't intend to return any values

    function x() {
      const x = 2;
      console.log("X", x);
      return x;
    }
    
    const revealed = () => x();
    console.log(revealed()); // 2
    
    const hidden = () => void x();
    console.log(hidden()); // undefined
    
  • In operator: it’s like hasOwnProperty in objects


Numbers & Dates

  • Use BigInt to represent very large numbers
  • Math can’t be used with BigInt values
  • you can't mix and match BigInt and Number values in the same operation
  • Number like 0777 (with leading 0 and numbers are less than 8)would be considered an octal in non strict mode
  • To write an octal number in ES5 add the prefix 0o777
  • Math.toPrecision ??
  • Creating Date without the new keyword returns only a date string not an object
  • Date.parse() to convert a date string to date object

Text formatting

  • When using a string literal let str = “str”

    JS converts it to a temporary String object apply any methods then returns the result discarding the object

  • Strings are immutable array-like object so you can't just assign a value to a certain index

    let str = str;
    str[2] = y; // won't do anything 
    
  • str.repeat(42) just repeats a string

  • charCodeStr.normalize() cause a string can be represented in different ways using char code normalize makes all the presentations are equal

  • Intl.collator(sort type) used for sorting and comparing strings for internationalization like handling different sort types in German

Regular Expressions

  • Use literal regular expression if the pattern is a constant for better performance

Indexed collections

  • Looping through a list of nodes? use this it’s more convenient

    You wont need to check the length

    You make sure the node is assigned to the var

    let divs = document.getElementsByTagName('div')
    for (let i = 0, div; div = divs[i]; i++) {
      /* Process div in some way */
    }
    
  • it is not advisable to iterate through JavaScript arrays using for...in loops, because normal elements and all enumerable properties will be listed.

  • How to call array methods on array-like objects

    Using prototype.call

    function printArguments() {
      Array.prototype.forEach.call(arguments, function(item) {
        console.log(item);
      });
    }
    
  • Typed arrays are array-like objects with a mechanism for accessing raw binary data

  • Typed arrays architecture is divided into buffer and view

    Buffer is a chunk of data that has no mechanism to access like an ArrayBuffer

    View is your way to access the buffer data it provides a context with data type (that is why it’s typed array it has a type!), starting offset and number of elements like a DataView

  • There are different typed array views and they have descriptive names like int8Arrays which means the view size is 8 bits/1byte

  • There is one special typed array view, Uint8ClampedArray, which clamps the values between 0 and 255. This is useful for Canvas data processing

Keyed Collections

  • Normal objects are not iterable
  • You can get the size of a Map easily, while you have to manually keep track of size for an Object
  • The iteration of maps is in insertion order of the elements. The order doesn’t matter in objects
  • Use maps if there is a need to store primitive values as keys because object treats each key as a string whether it's a number value, boolean value or any other primitive value
  • WeakMap keys are only objects and they are weakly held meaning that they are a target of garbage collection (GC) if there is no other reference to the object anymore
  • WeakMap keys are not enumerable you can’t have access to the list of keys
  • WeakMaps are usually used for privacy check an example
  • You can convert from set to array using spreed operator
  • WeakSets are collections of objects only
  • WeakSets are not enumerable

Working with objects (to reread)

  • Object.create() method. This method can be very useful, because it allows you to choose the prototype object for the object you want to create without having to define a constructor function. >> inheritance
  • You access forms in a document using document.forms

    document.forms[1] // returns first document appears in the document

    document.forms[‘my-form’] // returns the form with name property equals my-form

  • Getters and setters can be added to an object at any time after creation using the Object.defineProperties method

    var o = { a: 0 };
    
    Object.defineProperties(o, {
        'b': { get: function() { return this.a + 1; } },
        'c': { set: function(x) { this.a = x / 2; } }
    });
    
    o.c = 10; // Runs the setter, which assigns 10 / 2 (5) to the 'a' property
    console.log(o.b); // Runs the getter, which yields a + 1 or 6
    

Details of the object model (to reread)

  • Creating a new object from a function you can omit the parenthesis if there're no params

    const jane = new Engineer;
    
  • Method delegation can preserve memory resources because you only need one copy of each method to be shared by all instances

    function Greeter(name) {
      this.name = name || "John Doe";
    }
    
    Greeter.prototype.hello = function hello() {
      return "Hello, my name is " + this.name;
    };
    
    const george = new Greeter("George");
    const jack = new Greeter("jack");
    
    console.log(george.hello === jack.hello); // true (means they have the same reference)
    
  • In JavaScript, any function can create new objects. When it’s not a constructor function, it’s called a factory function like Object.create()

Using Promises

  • a promise is a returned object to which you attach callbacks, instead of passing callbacks into a function.
  • It's possible to chain after a failure, i.e. a catch, which is useful to accomplish new actions even after an action failed in the chain Like a finally in a try catch
  • Promises rejection events are of type [PromiseRejectionEvent](https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent) has as members a [promise](https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent/promise) property indicating the promise that was rejected, and a [reason](https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent/reason) property that provides the reason given for the promise to be rejected
  • All rejections are raised to global scope (either window or worker) And they come in two types
    • rejectionhandled Sent when a promise is rejected, after that rejection has been handled by the executor's reject function.
    • unhandledrejectionSent when a promise is rejected but there is no rejection handler available.
  • Promisifying setTimeout

    const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
    
    wait(10*1000).then(() => saySomething("10 seconds")).catch(failureCallback);
    
  • You can use Promise.resolve() and Promise.reject()to manually create an already resolved or rejected promise

  • Promise.all reusable compose function

    const applyAsync = (acc,val) => acc.then(val);
    const composeAsync = (...funcs) => x => funcs.reduce(applyAsync, Promise.resolve(x));
    

Next Read

Top comments (0)