console.log("Hello World");
Math.pow(2, 53) === Math.pow(2, 53) + 1; // true
Infinity, -Infinity, NaN, 0, -0.
0.1 + 0.2 === 0.3; // false
"abc" + "def"; // "abcdef"
"hello world"[4]; // "o"
UCS2 encoding.
Date.now(); // Milliseconds since Epoch (Jan 1 1970)
var today = new Date();
today.getDate();
today.getMonth();
today.getFullYear();
var a = 42;
var myArr = [a, 1, "Nick"];
myArr[0]; // 42
myArr[-1]; // undefined
myArr.length; // 3
myArr.length = 1; // array truncation
console.log(myArr); // [42]
var nick = {
name: "Nick",
age: 23
};
nick.name; // "Nick"
nick["age"]; // 23
// new properties can be added...
nick.favoriteBand = "Iron Maiden";
// and deleted
delete nick.age;
JavaScript Object Notation (JSON)
{
"data": 12345,
"from": "Nick"
}
var json = '{ "name": "Nick" }';
try {
var nick = JSON.parse(json);
nick.name; // "Nick"
} catch (e) {
console.error(e);
}
var dog = { name: "Winston", type: "Bulldog", };
JSON.stringify(dog); // '{ "name": "Winson", "type": "Bulldog" }'
var a;
a; // undefined
var b = null;
b; // null
Always define variables, use null to remove reference to a variable.
var a = 5;
// process a
a = null; // a no longer needed
Functions with no return value return undefined, and parameters not
passed are also undefined.
var re = /firefox/;
re.test("hello firefox, how are you?"); // true
"a1bb22ccc333dddd4444".match(/[0-9]{3}[a-z]{3}/)[0]; // "333ddd"
A quick reference is helpful in writing "regexes."
// named function
function addTwo (num) {
return num + 2;
};
// anonymous function assigned to a variable.
var addThree = function (num) {
return num + 3;
};
addThree(addTwo(1)); // 6
var hello = "hello";
function sayHello () {
// Notice that hello is not defined within this function.
return hello;
};
sayHello(); // "hello"
sayHello is a closure. It "closes over" the variable hello.
function add (addend1) {
return function (added2) {
return addend1 + addend2;
};
}
var addTwo = add(2);
addTwo(12); // 14
var a = 5;
typeof a; // "number"
a = "nick";
typeof a; // "string"
You may reassign variables values of different types.
1 + 2; // 3
"1" + "2"; // "12"
1 + "2"; // "12"
"1" + 2; // "12"
1 == "1" // true
1 === "1" // false
Double equals operator, ==, can be the source of many bugs. Use
triple equals, generally.
for (var i = 0; i < 10; ++i);
i; // 10
(function () {
for (var j = 0; j < 10; ++j);
})();
j; // undefined
var a = 5;
console.log(a); // 5
window.console.log(a); // 5
window.console.log(window.a); // 5
this.a; // 5
this === window; // true
(function context () { return this; })() === window; // true
function Dog (name, kind) {
this.name = name;
this.kind = kind;
};
var pet = new Dog("Winston", "English Bulldog");
pet.name; // "Winston"
function Vehicle (numWheels) {
this.numWheels = numWheels;
};
function Car (make, model, color) {
this.make = make;
this.model = model;
this.color = color;
};
// Car instances will inherit from one vehicle instance.
Car.prototype = new Vehicle(4);
var myCar = new Car("Porsche", "911 Turbo", "red"); // I wish...
myCar.numWheels; // 4
myCar.hasOwnProperty("make"); // true
myCar.hasOwnProperty("numWheels"); // false
myCar.hasOwnProperty("hasOwnProperty"); // false
Green is for instance properties.
function Dog (name) {
this.name = name;
this.bark = function () {
console.log(this.name + " barks!");
};
};
var doggie = new Dog("Winston");
doggie.bark(); // "Winston barks!"
var other = new Dog("Professor Barksalot");
other.bark(); // "Professor Barksalot barks!"
This works, but we are creating a new function object (this.bark) for
every instance of a Dog created.
function Dog (name) {
this.name = name;
};
Dog.prototype.bark = function () {
console.log(this.name + " barks!");
};
var doggie = new Dog("Winston");
doggie.bark(); // "Winston barks!"
var other = new Dog("Professor Barksalot");
other.bark(); // "Professor Barksalot barks!"
This works and every instance of Dog shares the same function object
(this.bark) for each instance. Reduces memory, but traversing
prototype chains is not free.
function Dog (name) {
this.name = name;
};
Dog.prototype.bark = function () {
console.log(this.name + " barks!");
};
var doggie = new Dog("Winston");
var other = new Dog("Professor Barksalot");
doggie.bark = function () {
console.log(this.name + " wonders 'What does the fox say?'");
};
doggie.bark(); // "Winston wonders 'What does the fox say?'"
other.bark(); // "Professor Barksalot barks!"
Here, we're not touching the shared prototype object. Instead, we're
assigning a single instance of Dog a new bark property. Calling bark
on doggie does not traverse the prototype chain. Calling bark on
other does.
function Dog (name) {
this.name = name;
};
Dog.prototype.bark = function () {
console.log(this.name + " barks!");
};
Dog.prototype.bark.call("Nick"); // "Nick barks!"
var dog = new Dog("Winston");
dog.bark.bind("Professor Barksalot")(); // "Professor Barksalot barks!"
dog.name; // "Winston"
function printArgs() {
for (var i = 0; i < arguments.length; ++i) {
console.log(arguments[i]);
}
};
printArgs(1, 2, 3); // 1, 2, 3
printArgs.call(null, 1, 2, 3); // 1, 2, 3
printArgs.apply(null, [1, 2, 3]); // 1, 2, 3
Function.prototype.call is itself variadic. So is Function.prototype.bind.
document.getElementById("myId");
document.getElementsByClassName("odd");
document.getElementsByTagName("a");
document.querySelector("#myId a.odd");
document.querySelectorAll("a.odd");
var ele = document.getElementById("addNode");
ele.parentNode;
ele.childNodes;
ele.previousSibling;
ele.nextSibling;
var siblings = Array.prototype.filter.call(
ele.parentNode.childNodes, function (child) {
return child !== ele;
}
);
NodeList and HTMLCollection objects aren't JavaScript Array objects,
but they have a length property which Array.prototype.filter needs,
so we can use call to change this. arguments is also not a JavaScript
Array object!
<div id="addNode"></div>
<script>
var target = document.getElementById("addNode");
var p = document.createElement("p");
p.textContent = "Hello World!";
target.appendChild(p);
</script>
<div id="removeNode">Remove me</div>
<script>
var target = document.getElementById("removeNode");
target.parentNode.removeChild(target);
</script>
<p id="dhtml">Hello World!</p>
<script>
var target = document.getElementById("dhtml");
target.style.color = "red";
target.style.fontSize = "40pt";
target.style.textShadow = "0px 90px 10px orange";
target.style.transform = "rotateY(-45deg) rotateX(35deg) rotateZ(-10deg)";
</script>
Hello World!
myEle.setAttribute("id", "myEle");
myEle.getAttribute("id"); // "myEle"
<p class="hello world" data-whatever="foo"></p>
<script>
p.classList.add("bar");
p.classList.remove("hello");
p.classList.toString(); // "world bar"
p.dataset.whatever; // "foo"
p.dataset.hello = "nick";
p.getAttribute("data-hello"); // "nick"
</script>
if (!Array.prototype.forEach) {
Array.prototype.forEach = function (callback, thisArg) {
if (!("length" in this)) {
throw new TypeError("this has no length property");
}
if (typeof callback !== "function") {
return;
}
for (var i = 0, len = this.length; ++i) {
callback.call(thisArg || null, this[i], i, this);
}
};
}
Array.prototype.forEach is available everywhere except pre IE9.
var hello = document.getElementById("hello");
hello.onclick = function (event) {
hello === event.target; // true
event.preventDefault; // don't follow links if <a> tag
console.log("hello world!");
};
onclick assigns a single callback function.
var hello = document.getElementById("hello");
hello.addEventListener("click", function (event) {
console.log("a");
});
hello.addEventListener("click", function (event) {
console.log("b");
});
addEventListener can be used to queue up multiple callback functions.
This example logs "a" then "b".
var hello = document.getElementById("hello");
hello.addEventListener("click", function once (event) {
hello.removeEventListener("click", once);
console.log("c");
});
By using a named function instead of an anonymous function, we can
remove event listeners.
<-- Fails -->
<script>document.getElementById("nick");</script>
<p id="nick">Hello</p>
<-- Succeeds -->
<p id="nick2">Hello</p>
<script>document.getElementById("nick");</script>
// position independent
document.addEventListener("DOMContentLoaded", function (e) {
document.getElementById("nick");
});
Having your JavaScript depend on the positioning of the script tag
within the DOM is brittle. Add event listener for DOMContentLoaded
or load to document.