javascript-notes-publish
book-body
author
Thava Alagu thavamuni@gmail.com
Version
0.1
Date
2025 February 24
Contents
local
This is a brief summary and useful notes about core JavaScript Language. This is not a comprehensive text book reference.
JavaScript is ubiquitous. It was born from browsers and is now used everywhere. At it's core, it is a decent programming language and it has it's strengths and weaknesses. Much of it's bad reputation came from inconsistent DOM implementations on browsers. However as a language, it is powerful and one of its kind.
As per Atwood's Law proposed by Jeff Atwood:
Any application that can be written in JavaScript, will eventually be
written in JavaScript.
JavaScript is now used to write programs in different areas where no one ever had originally imagined while it was invented for browser.
It is important to understand the history of JavaScript:
minitable
Year | Language/Std | Author | Comments |
---|---|---|---|
1995-1996 |
|
|
|
1996 |
|
|
|
1997 |
|
|
|
1999 |
|
|
|
2009 |
|
|
|
2015 |
|
|
|
2016 |
|
|
|
2017 |
|
|
You can learn javascript by using any editor of your choice. I recommend free Visual Studio Code editor
Chrome built-in developer tools is also very useful to run your front-end javascript code targetted for browser. You can invoke it by right click => Inspect in chrome.
It is also easier to learn javascript using standalone commandline shell:
The primary target audience of JavaScript is Web programmers, both client side and server side. The related standard of interest is DOM, Document object Model.
"Dynamic HTML" is a term to describe the combination of HTML, style sheets and scripts that allows documents to be animated. The W3C standard DOM (Document Object Model) standardizes the object model of XML and HTML documents to be exposed to the scripts.
The W3C DOM specifications provide bindings only to Java and ECMAScript. It would be useful to skim through the ECMAScript bindings provided by DOM standard.
JavaScript (or ECMAScript) is Object-based language, not class-based language. The basic language and host facilities are provided by objects. There is a notion of object, properties, attributes, built-in type, primitive value, function object and so on.
For people who are familiar with only 'class' based languages like Java and C++, it may be bit difficult to comprehend Javascript's approach. For such people there are also alternaive choices like Typescript instead of Javascript. Typescript is a superset of Javascript. It adds stronger type system and classes. A Typescript program gets compiled to generate Javascript.
It is important that we familiarize ourselves with the exact meaning of these terms in the context of Javascript.
minitable
Term |
|
---|---|
object |
|
property |
|
builtin-types |
|
primitive-value |
|
builtin-objects |
|
Constructor |
|
Prototype |
|
JavaScript supports prototype based inheritance.
minitable
typeof(t) |
|
---|---|
Undefined |
|
Boolean |
|
Number |
|
String |
|
Object (native and "object" doesn’t implement [[Call]]) |
|
Object (native and "function" implements [[Call]]) |
|
Object (host) | Implementation-dependent |
Following examples can be executed either using Chrome browser console window or node command line shell.
$ node
> 5 + 10
15
> Math.pow(2, 5)
32
> 5/3
1.6666666666666667
> Math.floor(5/3)
1
> 5, 7, 21 # or (5, 7, 21)
21
> a = b = c = 100
100
> b = (c=5, d=10, 20) # Embedded assignment in expression is OK.
20
> 5 < 10
true
> 5 && 10
10 // <== It is not a boolean!
> !! (5 && 10)
true // <== Use this to convert expr to boolean.
> 5 || 10
5
> 5 & 1
1
> 2 << 5
64
> typeof 5
'number'
> aaa
ReferenceError: aaa is not defined
> 2 * 'some'
NaN
> a++
100
> a
101
> ++a
102
> a += 10
112
> 6 + '5' // Integer promoted to string. Not the other way.
'65'
> parseInt('123Hello')
123
> parseInt('08') <== Treats as Octal.
0
> parseInt('08', 10) <== Use Radix always
8
> a = 10; b = 30 ; eval (' a * b ') ;
300
> 'hello ' + ' world'
"hello world"
> typeof 'hello'
'string'
> a = 'hello world'
> a.<Tab> # Autocomplete works on node.js shell.
a.__defineGetter__ a.__defineSetter__ a.__lookupGetter__
a.__lookupSetter__ a.constructor a.hasOwnProperty
a.isPrototypeOf a.propertyIsEnumerable a.toLocaleString
a.toString a.valueOf
a.anchor a.big a.blink
a.bold a.charAt a.charCodeAt
a.concat a.constructor a.fixed
a.fontcolor a.fontsize a.indexOf
a.italics a.lastIndexOf a.length
a.link a.localeCompare a.match
a.replace a.search a.slice
a.small a.split a.strike
a.sub a.substr a.substring
a.sup a.toLocaleLowerCase a.toLocaleUpperCase
a.toLowerCase a.toString a.toUpperCase
a.trim a.trimLeft a.trimRight
a.valueOf
> a.substring(0,5)
'hello'
> a.substring(5,11) # a.slice() also does samething with minor differences.
' world'
> a.substr(5,6)
' world'
> a.length
11
> typeof a
'string'
> b = String(123) # Convert number to primitive string
'123'
> typeof b
'string'
> b = String('hello world') # without new operator, it is primitive type.
> a == b
true
> c = new String('hello world') # It is now 'object' not 'string' !
> typeof c
"object"
> a == c # Primitive object promoted to String to compare true!
true
Array is a built-in object of built-in Object type. It can also be used like a type since it defines a constructor.
> a = [1, 2, 3]
> b = [1, 2, 3]
> a == b
false # They are different Objects.
> a.push(4)
[1, 2, 3, 4]
> a.unshift(10) # Push at front
[10, 1, 2, 3, 4]
> a.shift() # Pop from font
10
> a.concat(b) # Creates new list a + b
[1, 2, 3, 1, 2, 3]
> a # a remains unchanged.
[1, 2, 3]
// Note: There is no built-in a.extend(b) method that will mutate a.
> a + b # converts to String and joins.
'1,2,31,2,3' # To join, use concat
> a = [1, 2, 3, 4, 5, 6]
> a.slice(2,4) # similar to python a[2:4]
[3, 4] # a[2], a[3]
>a.<Tab>
a.__defineGetter__ a.__defineSetter__ a.__lookupGetter__ a.__lookupSetter__
a.constructor a.hasOwnProperty a.isPrototypeOf a.propertyIsEnumerable
a.toLocaleString a.toString a.valueOf
a.concat a.constructor a.every a.filter
a.forEach a.indexOf a.join a.lastIndexOf
a.length a.map a.pop a.push
a.reduce a.reduceRight a.reverse a.shift
a.slice a.some a.sort a.splice
a.toLocaleString a.toString a.unshift
> a = [10, 20, 30]
[ 10, 20, 30 ]
> delete a[1] # delete on array element creates hole using 'undefined'
true
> a
[ 10, undefined x 1 , 30 ]
> a[1]
undefined
> a.length # length remains unchanged.
3
> a.splice(0, 2) # Really delete 2 elements starting from index 0.
[ 10, undefined x 1 ]
> a
[ 30 ]
> a = [10, 20, 30]
> for (i in a) console.log(i) # This prints the keys in array.
0
1
2
> a.some = 200 # Don't mix non-numeric index into array!
> a['abc'] = 300 # This is same as a.abc = 300
> for (i in a) console.log(i)
0
1
2
some
abc
> for (i in a) console.log(typeof(i))
string
string
string
string
string # All indexes stored as string internally.
> c = new Array(10) # Array is an object as well as a type!
[undefined × 10] # Array.constructor defines the type constructor.
> a = [1, 2, 3]; typeof a
"object"
> a instanceof Array
true
> a.constructor
[Function: Array]
Object is the only non-primitive built-in type.
> a = { 'one' : 1, 'two': 2 } # Creating object using literal
> typeof a
"object"
> for (i in a) console.log(i)
one
two
> a = new Object()
Object # Chrome displays a clickable, explorable empty Object icon.
{} # node.js shell displays the empty object.
> a.v1 = 200 # Perfect for using as associative array.
> a['v2'] = 300 # It is same as a.v2 = 300
> for (i in a) console.log(i)
v1
v2
> F = function() { this.var1 = 100; this.var2 = 200 }
> fobj = new F() # New object created which becomes 'this' object.
{ var1: 100, var2: 200 }
> a.<tab> # This autocomplete operation works only on node.js shell.
a.__defineGetter__ a.__defineSetter__ a.__lookupGetter__
a.__lookupSetter__ a.constructor a.hasOwnProperty
a.isPrototypeOf a.propertyIsEnumerable a.toLocaleString
a.toString a.valueOf
a.v1 a.v2
Note: Object does not contain any enumerable properties, hence suitable
for implementing hash/associative array with string keys.
Javascript supports object based inheritance instead of classes. It
makes use of prototype
property to trace the parent object hierarchy:
> function object(o) {
function F() {}
F.prototype = o;
return new F();
}
> obj = new Object()
> childobj = object(obj) # childobj is based on parent object obj.
> typeof true
"boolean"
> a = [1, 2, 3]
> JSON.stringify(a) # works for nested object as well.
'[1,2,3]'
> di
{ a: 10, b: 20 }
> JSON.stringify(di)
'{"a":10,"b":20}'
> print(JSON.stringify(di, null, 4)) # Nicely formatted output
{
"a": 10,
"b": 20
}
> function f() { console.log('hello world') }
undefined
> f.toString()
'function f() { console.log(\'hello world\') }'
> n = null
> n && n.value # Use this pattern to avoid Null reference.
null
> null == undefined
true
> null === undefined
false
Examples using browser :
// alert(), confirm(), prompt() work in browsers.
> alert('hello!!!')
> r = confirm('Press Ok or Cancel')
> r
true // or false
> console.log('You pressed ' + (r && 'OK' || 'Cancel'))
> val = prompt('Enter Value ', '0')
> val
> typeof(val)
'string'
// Following examples work with node.js
> u=require('util'); u.puts('hello!') // Prints: 'hello!'
> process.stdout.write('hello!') // Prints: 'hello!'
// readline will be useful in node.js script, not at the command line:
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false
});
rl.on('line', function (cmd) { console.log('You just typed: '+cmd); });
Statements can be of following kinds:
Block VariableStatement EmptyStatement ExpressionStatement
IfStatement IterationStatement ContinueStatement BreakStatement
ReturnStatement WithStatement LabelledStatement SwitchStatement
ThrowStatement TryStatement
Examples:
{ x++; y++; }
// Note: There is no block level scope for variables.
var x = 1; { var x = 2; } ; alert(x); // outputs 2
function f() { var i = 10; } // The i is local, not global variable.
function g() { i = 10; } // The i is global.
a = 10; // (a = 10) evaluates to 10. Expression Statement.
if (x == y)
f(x)
else if (x > z)
g(x)
else
h(x)
Examples:
do x = f(x); while ( x < 1000 );
while ( notdone ) { f(x); g(x); }
for (a = b+c; a < 10 ; a++ ) f(a);
for ( var i=0; i < a.length ; i++ ) f(a[i]);
for ( i in a ) f(a[i]);
for ( var i in (c=a.concat(b)) ) f(c[i]);
outerloop: while (!finished) {
f(x);
innerloop: while (!completed) {
g(x);
if (condition_1) continue outerloop;
if (condition_2) break outerloop;
if (condition_3) continue;
if (condition_4) break;
h(x);
}
}
with (obj) {
a = 10; // set obj.a = 10 if obj.a exists ; else set global a=10
b = 20; // set obj.b = 20 iff obj.b exists;
}
with (document.getElementById("blah").style) {
background = "black";
color = "blue";
border = "1px solid green";
}
// Because of the confusing semantics it is deprecated.
// c-style switch but case expression need not be constant!
x = 'hello'; y = 'hell' ; z = 'o';
switch(x) // Allows strings
{
case 1 : console.log('it is 1'); break;
case y+z : console.log('it is y+z'); break;
default : console.log('it is default'); break;
}
// Prints: it is y+z
You can control the error handling by catching errors that are generated. These are the primary error types:
When user defined errors are thrown, it is typical to throw Error() object, but you can also simply throw anything like just plain string:
throw new Error('Timeout occurred!');
throw 'Timeout!';
Example:
function f() {
try {
val = prompt('Enter Option: 1:Throw; 2:return early; 3:Continue;');
if (val == '1')
throw 'Option1-Error-thrown'; // finally will execute.
else if (val == '2')
return 'early'; // finally will execute before return.
else if (val > 3)
throw new RangeError('Invalid Option');
}
catch (err){
// You can also do... switch (err.name) ... case 'RangeError': ...;
// if (typeof err == 'string') then err.name == undefined;
console.log('Caught error name: ' + err.name);
console.log('Description:' + err);
}
finally{
console.log('Executing finally now...');
}
return 'last';
}
A function can be declared like below:
function f(x) { console.log('I am function f. Arg x is ' + x); }
Above declaration is equivalent to following expression:
f = function(x) { console.log('I am function f. Arg x is ' + x); }
Example:
function g(x)
{
if (x > 10) return; // return value is undefined
if (x == 10) return x;
y = 100; // y becomes a global variable.
var z = 200; // z is local variable.
{ var z = 300; } // Blocks don't have new scope.
console.log('z is : ' + z); // Prints: z is: 200
// You can call this function as:
// g(); // x == undefined
// g(10, 20, 30); // x == 10; Extra args ignored!
console.log(arguments); // It is array of all arguments passed.
}
// You can use anonymous functions in order to use many temporary variables...
(function(){
var tmp1 = 1; var tmp2 = 1;
global_var1 = 100;
....
)();
// Above function call creates only one global_var1;
// The other local variables do not corrupt global namespace.
Following example illustrates how to create and use an object in an object oriented style of programming:
function Car() { this.wheels = 4 ; this.color = 'red' ; }
c = Car(); <== c becomes undefined
c = new Car(); <== Get a nice object {wheels:4, color:'red'}
function Car() { this.wheels = 4 ; this.color = 'red' ; return this; }
c = Car(); <== c gets global object this !!! ; No warnings !!!
c = new Car();
{ wheels: 4, color: 'red' }
Car.model = 'benz'
c = new Car(); <== Does not inherit new properties.
{ wheels: 4, color: 'red' }
c.model
undefined
Car.prototype.model = 'benz' <== Every Function has "prototype" predefined to {}
c = new Car();
{ wheels: 4, color: 'red' } <== By Default does not show parent obj props
c.model
'benz'
c.constructor
{ [Function: Car] }
c.constructor.constructor
[Function: Function] <== Leaf constructor/object
c.constructor.constructor.constructor == c.constructor.constructor
true
c.constructor.constructor.prototype
[Function: Empty] <== Equivalent to {}
c.constructor.prototype // Same as Car.prototype
{ 'benz' }
c.constructor.prototype.constructor == c.constructor
true <== True for any object.
Note: While dumping "prototype" object you may want to skip printing the properties twice,
by checking .e.g. if (obj.constructor.prototype == obj) obj = obj.constructor.
Following points worth noting:
Only Single inheritance style is supported.
The inheritance is prototype based, not class based.
Sharing of parent objects is done with Copy-on-write mechanism:
NewObject ---> ParentObject [ properties created in NewObject as CopyOnWrite ]
Deleting object elements only deletes at 'top-level' -- if it exists in prototype it may be visible for read even after deletion:
> c = new Car()
> c.model
'benz'
> c.model = 'fusion'
> delete(c.model)
> c.model
'benz'
> delete(c.model)
> c.model
'benz' # property in prototype is always available for reading.
Free objects are garbage collected
Object.prototype (is the last in the linkage hierarchy). It provides very few useful methods that every Object must inherit-- this includes toString(). By default, there is no clone() or equals() method implementation available.
Object itself provides some useful methods such as keys(), hasOwnPropertyNames(), create(), etc. These are to be used more like global functions. These methods are not inherited by the objects.
Ready made objects can be easily reorganized for inheritance. Object customization is lot easier than doing the same thing with classes.
Node.js is a platform to develop standalone JavaScript based applications. Node.js uses an event-driven, non-blocking I/O model.
You can import different modules like below:
var net = require('net');
var server = net.createServer(function(c) { // connection listener ... })
var os = require('os')
console.log(os.hostname())
$ node -e 'var sys = require("sys"); sys.puts("hi world!");
$ node
> util = require('util') # sys module renamed to util in some versions.
> util.puts('hello')
> print = util.puts
> print('hello')
> mymod = require('/abs/path/to/mymod.js') ;
> u=require('util')
{ format: [Function],
print: [Function],
puts: [Function],
debug: [Function],
error: [Function],
inspect: [Function: inspect],
isArray: [Function: isArray],
isRegExp: [Function: isRegExp],
isDate: [Function: isDate],
isError: [Function: isError],
p: [Function],
log: [Function],
exec: [Function],
pump: [Function],
inherits: [Function],
_deprecationWarning: [Function] }
The other modules include: Cluster, Crypto, File System (fs), HTTP, Net, OS, Readline, etc.