this
refers to the global object.this
refers to the parent object inside that function.new
operator, this
refers to the newly created object inside that function.call
or apply
, this
refers to the first argument passed to call
or apply
. If the first argument is null
or not an object, this
refers to the global object.ul
element with several child elements:
<ul id="parent-list"> <li id="post-1">Item 1</li> <li id="post-2">Item 2</li> <li id="post-3">Item 3</li> <li id="post-4">Item 4</li> <li id="post-5">Item 5</li> <li id="post-6">Item 6</li> </ul>Let's also say that something needs to happen when each child element is clicked.You could add a separate event listener to each individual
li
element, but what if li
elements are frequently added and removed from the list? Here's a very basic JavaScript snippet which illustrates event delegation:
// Get the element, add a click listener... document.getElementById("parent-list").addEventListener("click", function(e) { // e.target is the clicked element! // If it was a list item if(e.target && e.target.nodeName == "LI") { // List item found! Output the ID! console.log("List item ", e.target.id.replace("post-", ""), " was clicked!"); } });
function foo() { } typeof foo.prototype // ‘object’And here is the example of prototype inheritance
function Dog() { } Dog.prototype.bark = function() { console.log(‘woof!’); }; var fido = new Dog(); fido.bark(); // ‘woof!’JavaScript uses an inheritance model called “differential inheritance”. What that means is that methods aren’t copied from parent to child. Instead, children have an “invisible link” back to their parent object. What actually happens when I write
fido.bark()
is this:Dog.prototype
.Dog.prototype.bark
, and calls it with this bound to fido.function notAClosure() { var shortLivedVariable = "I'm only here for a little while"; return shortLivedVariable; } notAClosure(); // returns "I'm only here for a little while"In a closure those variables stick around for a while longer since there is a reference to the variables after the function returns.
function aClosure() { var longLivedVariable = "I'm here for a long time"; var innerFunction = function inner() { return longLivedVariable; } return innerFunction; } var closure = aClosure(); // returns a reference to innerFunction closure(); // returns "I'm here for a long time"This is a good example of closure:
function cat(name) { return { sayName: function() { return name; } } } var fluffy = cat('Mr. Fluffy'); fluffy.name // returns undefined fluffy.sayName() // returns 'Mr. Fluffy' var whiskers = cat('Whiskers'); whiskers.sayName() // returns 'Whiskers'
function takesACallback(callback) { // do some interesting things here return "The callback says: " + callback(); } takesACallback(function() { return "I'm the callback!"; }); // returns "The callback says: I'm the callback!"Anonymous functions are typical used as callbacks.
In JavaScript, the Module pattern is used to further emulate the concept of classes in such a way that we’re able to include both public/private methods and variables inside a single object, thus shielding particular parts from the global scope. - Addy Osmani, Learning Javascript Design Patterns
var myModule = (function(){ var privateVar = "abc"; var privateMethod = function() { console.log(privateVar); }; return { setVar: function(str) { privateVar = str; }, getVar: function() { return privateVar; }, printVar: privateMethod }; })();Classical inheritance
function Person (name) { this.name = name; } Person.prototype.sayMyName = function() { console.log("My name is " + this.name); }; Person.prototype.walk = function() { console.log("I am walking..."); }; function Student(name){ Person.call( this, name ); } Student.prototype = new Person(); // Student.prototype = Object.create(Person.prototype); Student.prototype.read = function() { console.log("I am reading..."); }; var neil = new Student("neill"); neil.sayMyName(); neil.walk(); neil.read(); console.log(neil instanceof Student); // true console.log(neil instanceof Person); // true
var obj = {num:2}; var functionName = function(arg1, arg2, arg3) { return this.num + arg1 + arg2 + arg3; }; functionName.call(obj, 1, 2, 3) //return 8 functionName.apply(obj, [1, 2, 3]) //also returns 8, but argument is an array var anotherFunction = functionName.bind(obj) //returns function with object anotherFunction(1, 2, 3) //return 8