I am currently reading "Javascript - The Good Parts" by Douglas Crockford. I would recommend this book to anyone who works with javascript or jQuery or any other js based libraries. In this blog, I would note down few of the important lessons from this book and some other books I have read so far on this subject -
- Should not use the comments block /* */ because if you are using regular expressions, this syntax might create problem.
- js reserved words: abstract, boolean, break, byte, case, catch, char, class, const, continue, debugger, default, delete, do, double, else, enum, export, extends, false, final, finally, float, for, function, goto, if, implements, import, in, instanceof, int, interface, long, native, new, null, package, private, protected, public, return, short, static, super, switch, synchronized, this, throw, throws, transient, true, try, typeof, var, volatile, void, while, with.
- keywords dont include undefined, NaN and infinity.
- js has only one number type represented by 64 bit floating type.
- escape character is backslash (\)
- all characters in js are 16bits wide
- js doesnt have a character type. Character in js is a string with just one character in it.
- blocks in js do not create new scope.
- falsy values: false, null, undefined, '', 0, NaN. Everything else including true, string 'false' and all objects are true.
- Should use === and !== for equality checks
- hasOwnProperty() - determine whether the property name is truly a member of the object or was found on the prototype.
- simple types: numbers, strings, booleans, null and undefined. Everything else is object.
- || can be used to fill in default values like var price = product.price || 0;
- && can be used to guard against TypeError exception. TypeError is thrown if we try to retrieve value from undefined. For ex. customer.order && customer.order.orderNumber
- objects are collections of name/value pairs having a hidden link to a prototype object. Objects produced from object literals are linked to Object.prototype.
- objects are passed around by reference.
- every object has a prototype object linked to it. While retrieving, if the object lacks the property name, then js attempts to look in the prototype object. If that prototype object lacks the property, js looks into its prototype until it bottoms out. At that point, it sets the value to undefined.
- Just like inheritance, when we change an object's property value that is coming from the prototype, it doesnt change the prototype object's property value.
- avoid using for in instead use for.
- avoid global variables. a global variable is basically a direct child of browser's window object.
- anytime a variable is declared without using var keyword, the variable will be a global variable.
- Functions
- functions are objects
- function objects are linked to Function.prototype which itself is linked to Object.prototype
- function also has 2 additional hidden properties: function's context and the code that implements function's behavior.
- every function object also has a prototype property. Its value is an object with a constructor property whose value is the function. This is different from the hidden link to Function.prototype.
- Since functions are objects, functions can have methods.
- functions can be defined inside functions. An inner function of course has access to the parameters and variables of the function it is nested within. This is called closure.
- This is a function literal: function add(a,b){ return a+b;};
- If name is not provided, it becomes an anonymous function. For ex. var add = function (a,b){ return a+b;};
- Avoid creating functions in a for loop. Instead create a function outside of the loop so that variables used have closure.
- each function has a name. If the name is empty, its an anonymous function. When we declare a function like var abc = function(){}; abc is not the name of the function. The name is still empty string.
- This function name is valid throughout the scope in which function is declared. If the function is at the global scope, a property using the function name is created on the window object that references the function.
- Named functions are in scope within the entire function in which they are referenced. However variables are in scope only from the point they are declared to the end of declaration.
- A function can be invoked in 4 ways
- as a function (normal way) (in global context this = window)
- as a method (when its tied to an object) (this = object that called the method) - When we do something like : var obj = { abc = somefunc}; then abc is just assigned a reference to somefunc. somefunc remains its own independent function.
- as a constructor in which a new object is created - invoking is done as a constructor when a function is invoked by using the new keyword like new Somefunc(); When a constructor is created the following things happen
- an empty object is created
- the empty object is passed to the function as the context
- if no explicit return value is defined in the function, the empty object is returned as the return value
Since constructors are usually written differently and have a different purpose a general naming convention is to name the function based on a noun and with uppercase letter. - via apply() or call() in which case we can change the context in which these functions are called
- All function invocations are passed two parameters implicitly - arguments and this
- Javascript is prototypal language which means that objects directly inherit from other objects.
- Arrays
- An array like nums_arr = ['A', 'B'] and an object literal like nums_ol = {'0':'A', '1':'B'} are objects containing 2 properties and those props have exactly the same name and values. The difference is that nums_arr inherits from Array.prototype while nums_ol inherits from Object.prototype. Therefore, nums_arr has a larger set of useful methods. Also, nums_arr has a length property which nums_ol doesnt.
- In JS arrays 1 array can contain items of any type. They dont need to be of one type.
- The length property on array is the largest integer property name in the array plus one. This is not necessarily the number of properties in the array. So in an empty array if we define something like myArr[10] = "ABC", the length of myArr would become 11 although myArr only contains one object.
- To add an object to array we use the push method.
- To delete an object from array we use the splice method like so myArr.splice(2,4). 2 is the ordinal position in the array and 4 is the number of items to delete.
- When to use an array and when to use an object: when the property names are small sequential integers, use array. Otherwise use an object.
- getComputedStyle is used to get the final used value of any css property. For ex, getComputedStyle(mydiv).border will get the border property of mydiv element.
- It is recommended to keep all js file references just before the </body> tag. Placing them in <head> makes them to load first even before the page starts to render. Page starts rendering when it encounters the <body> tag.
- In the script tag we can use the async keyword. It means that the page need not wait for the script to get downloaded and executed before loading. Async scripts are guaranteed to execute before the page's load event. They might get executed before or after the DOMContentLoaded event.