Create a gist now

Instantly share code, notes, and snippets.

@azat-co /JSFUN.md
Last active Jun 10, 2017

What would you like to do?
JavaScript FUNdamentals

JS FUNdamentals

If it's not fun, it's not JavaScript.

Expressiveness

Programming languages like BASIC, Python, C has boring machine-like nature which requires developers to write extra code that's not directly related to the solution itself. Think about line numbers in BASIC or interfaces, classes and patterns in Java.

On the other hand JavaScript inherits the best traits of pure mathematics, LISP, C# which lead to a great deal of expressiveness (and fun!).

More about Expressive Power in this post: What does “expressive” mean when referring to programming languages?

The quintessential Hello World example in Java (remember, Java is to JavaScript is what ham to a hamster):

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}

The same example in JavaScript:

console.log('Hello World')

or from within an HTML page:

<script>
document.write('Hello World')
</script>

JavaScript allows programmers to focus on the solution/problem rather that to jump through hoops and API docs.

Loose Typing

Automatic type casting (mostly). Only a few primitives types:

  1. string
  2. number (both integer and real)
  3. boolean
  4. undefined
  5. null

Everything else is an object, i.e., mutable keyed collections. Read Stackoverflow on What does immutable mean?

Also, in JavaScript there are String, Number and Boolean objects which contain helpers for the primitives:

'a' === new String('a') //false

but

'a' === new String('a').toString() //true

or

'a' == new String('a') //true

By the way, == performs automatic type casting while === not.

Object Literal Notation

var obj = {
   color: "green",
   type: "suv",
   owner: {
      ...
   }
}

Remember that functions are objects?

var obj = function () {
   this.color: "green",
   this.type: "suv",
   this.owner: {
      ...
   }
}

Functions

Functions are first-class citizens, and we treat them as variables, because they are objects! Yes, functions can even have properties/attributes.

Create a Function

var f = function f () {
   console.log('Hi');
   return true;
}

or

function f () {
  console.log('Hi');
  return true;
}

Function with a property (remember functions are just object that can be invoked, i.e. initialized):

var f = function () {console.log('Boo');}
f.boo = 1;
f(); //outputs Boo
console.log(f.boo); //outputs 1

Note: the return keyword is optional. In case its omitted the function will return undefined upon invocation.

Pass Functions as Params

var convertNum = function (num) {
 return num + 10;
}

var processNum = function (num, fn) {
   return fn(num);
}

processNum(10, convertNum);

Invocation vs. Expression

Function definition:

function f () {};

Invocation:

f();

Expression (because it resolve to some value which could be a number, a string, an object or a boolean):

function f() {return false;}
f();

Statement:

function f(a) {console.log(a);}

Arrays

Arrays are also objects which have some special methods inherited from Array.prototype global object. Nevertheless, JavaScript Arrays are not real arrays. Instead, they are objects with unique integer (usually 0-based) keys.

var arr = [];
var arr2 = [1, "Hi", {a:2}, function () {console.log('boo');}];
var arr3 = new Array();
var arr4 = new Array(1,"Hi", {a:2}, function () {console.log('boo');});

Prototypal Nature

There are no classes in JavaScript because objects inherit directly from other objects which is called prototypal inheritance: There are a few types of inheritance patterns in JS:

  • classical
  • pseudo-classical
  • functional

Example of the functional inheritance pattern:

var user = function (ops) {
  return { firstName: ops.name || 'John'
         , lastName: ops.name || 'Doe'
         , email: ops.email || 'test@test.com'
         , name: function() { return this.firstName + this.lastName}
         }
}

var agency = function(ops) {
  ops = ops || {}
  var agency = user(ops)
  agency.customers = ops.customers || 0
  agency.isAgency = true
  return agency
}

Conventions

Most of these conventions (with semi-colons being an exception) are stylistic, and highly preferencial and don't impact the execution.

Semi-Colons

Optional semi-colons, except for two cases:

  1. In for loop construction: for (var i=0; i++; i<n)
  2. When a new line starts with parentheses, e.g., Immediately-Invoked Function Expression (IIFE): ;(function(){...}())

camelCase

cameCase, except for class names which are CapitalCamelCase, e.g.,

var MainView = Backbone.View.extend({...})
var mainView = new MainView()

Naming

_,$ are perfectly legitimate characters for the literals (jQuery and Underscore libraries use them a lot).

Private methods and attributes start with _ (does nothing by itself!).

Commas

Comma-first approach

var obj = { firstName: "John"
          , lastName: "Smith"
          , email: "johnsmith@gmail.com"
          }

Indentation

Usually it's either tab, 4 or 2 space indentation with their supporters' camps being almost religiously split between the options.

White spaces

Usually, there is a space before and after =, +, { and } symbols. There is no space on invocation, e.g., arr.push(1);, but there's a space when we define an anonymous function: function () {}.

No Modules

At least until ES6, everything is in the global scope, a.k.a. window and included via <script> tags. However, there are external libraries that allow for workarounds:

Node.js uses CommonJS-like syntax and has build-in support for modules.

To hide your code from global scope, make private attributes/methods use closures and immediately-invoked function expressions (or IIFEs).

Immediately-Invoked Function Expressions (IIFEs)

(function () {
window.yourModule = {
...
};
}());

This snippet show an example of a object with private attribute and method:

(function () {
window.boo = {
  var _a = 1;
  var inc = function () {
    _a++; 
    console.log(_a);};
  };
  return {
    increment: inc
  }; 
}());
var b = window.boo();
b.increment();

keyword "this"

Mutates/changes a lot (especially in jQuery)! Rule of thumb is to re-assign to a locally scoped variable before attempting to use this inside of a closure:

var app = this
$('a').click(function(e){
  console.log(this) //most likely the event or the      target anchor element
  console.log(app) //that's what we want!
  app.processData(e)
 })

When in doubt: console.log!

Pitfalls

JS is the only language that programmers think they shouldn't learn

ajduke commented Feb 23, 2014

At location https://gist.github.com/azat-co/5955726#object-literal-notation
the second listing of specifying function, should contain the '=' instead of ':' (colon)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment