"With great power comes great responsibility"
Uncle Ben
// object literal a.k.a. Singleton
var myDog = {};
// ES5 Object.create method from prototype
var myDog = Object.create(Dog.prototype);
// constructor call (uses this to set properties)
var myDog = new Dog();
function Dog(name, breed) {
this.name = name;
this.breed = breed;
this.bark = function() {
return this.name + ': woof, woof, woof!';
};
}
var myDog = new Dog('Sherlock', 'beagle');
console.log(myDog.bark());
function Dog(name, breed) {
this.name = name;
this.breed = breed;
}
Dog.prototype.bark = function() {
return this.name + ': woof, woof!';
};
}
var myDog = new Dog('Sherlock', 'beagle');
console.log(myDog.bark());
var myDog = (function(name, breed) {
var getBarkStyle = function() {
return (breed === 'husky')? 'woooooow!': 'woof, woof!';
};
return {
bark: function() {
return name + ': ' + getBarkStyle();
}
};
})('Sherlock', 'beagle');
console.log(myDog.bark());
var myDog = (function(name, breed) {
function getBarkStyle() {
return (breed === 'husky')? 'woooooow!': 'woof, woof!';
};
function bark() {
return name + ': ' + getBarkStyle();
};
return {
name: name,
bark: bark
};
})('Sherlock', 'beagle');
console.log(myDog.bark());
define([], function() {
return {
sum: function(numberA, numberB) {
return numberA + numberB;
}
};
});
// Pure JS
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://code.jquery.com/jquery-latest.js', true);
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status === 200) {
console.log('success');
}
};
// jQuery
$.get('http://code.jquery.com/jquery-latest.js', function(data) {
console.log('success');
});
var factorialFacade = (function() {
var intermediateResults = [0, 1];
function calculate(n, stats) {
if (intermediateResults[n] === undefined) {
stats.ops++;
intermediateResults[n] = n * calculate(n - 1, stats);
}
return intermediateResults[n];
}
return {
factorial: function(n) {
var stats = { ops: 0 },
result = (n > 0 && n % 1 === 0)? calculate(n, stats): 0;
return n + '! = ' + result + ' (' + stats.ops + ' operations)';
}
};
})();
var consoleObserver = function(event, msg) {
if (event === 'goal') {
console.log('Team ' + msg.team + ' just scored! ' + msg.score);
}
}
var htmlObserver = function(event, msg) {
if (event === 'goal') {
$('h3').text('Team ' + msg.team + ' just scored! ' + msg.score);
}
}
var soccerMatchSubject = (function(teamA, teamB) {
var scoreTable = {};
scoreTable[teamA] = scoreTable[teamB] = 0;
var observers = [];
function notify() {
var args = arguments;
$.each(observers, function(index, observer) {
observer.callback.apply(observer.context, args);
});
}
return {
addObserver: function(fn) {
observers.push({ context: this, callback: fn });
},
//... continues on slide below
//... from slide above
goal: function(team) {
scoreTable[team]++;
score = teamA + ' ' + scoreTable[teamA] + ' x ' +
scoreTable[teamB] + ' ' + teamB;
notify('goal', { team: team, score: score });
}
};
})('Brazil', 'Spain');
soccerMatchSubject.addObserver(consoleObserver);
soccerMatchSubject.addObserver(htmlObserver);
$('button').click(function(e) {
e.preventDefault();
soccerMatchSubject.goal(this.innerHTML);
});
var mediator = { channels: {}, subscribe: function(channel, fn) { if (!mediator.channels[channel]) mediator.channels[channel] = []; mediator.channels[channel].push({ context: this, callback: fn }); }, publish: function(channel){ if (!mediator.channels[channel]) return; var args = Array.prototype.slice.call(arguments, 1); $.each(mediator.channels[channel], function(index, subscriber) { subscriber.callback.apply(subscriber.context, args); }); }, installTo: function(publisher){ publisher.subscribe = mediator.subscribe; publisher.publish = mediator.publish; }
};
var soccerMatchSubject = (function(teamA, teamB) {
var scoreTable = {};
scoreTable[teamA] = scoreTable[teamB] = 0;
return {
goal: function(team) {
scoreTable[team]++;
score = teamA + ' ' + scoreTable[teamA] + ' x ' +
scoreTable[teamB] + ' ' + teamB;
this.publish('loggers', 'goal', { team: team, score: score });
}
};
})('Brazil', 'Spain');
mediator.installTo(soccerMatchSubject);
soccerMatchSubject.subscribe('loggers', consoleObserver);
soccerMatchSubject.subscribe('loggers', htmlObserver);
var NewEmailModule = function(from) {
return {
newEmail: function(email) {
email.from = from;
this.publish('email', { email : email });
}
};
};
var myNewEmail = NewEmailModule('tgarcia@avenuecode.com');
mediator.installTo(myNewEmail);
var MailboxModule = function(owner, channel) {
var emails = [];
return {
receiveEmail: function(message) {
if (message.email.to === owner) {
emails.push(message.email);
this.publish(channel, { owner: owner, emails: emails });
}
}
};
};
var myMailbox = MailboxModule('tgarcia@avenuecode.com', 'my-mailbox');
mediator.installTo(myMailbox);
mediator.subscribe('email', myMailbox.receiveEmail);
var RenderMailboxModule = function(selector) { var el = $(selector); return { render: function(message) { var frag = $(document.createDocumentFragment()); $.each(message.emails, function(index, email) { frag.append('<h3>[' + index + '] ' + email.subject + '</h3>') .append('<h4>From: ' + email.from + '</h4>') .append('<p>' + email.content + '</p>'); }); el.html(frag); } }; };
var myRenderMailbox = RenderMailboxModule('#my-mailbox'); mediator.subscribe('my-mailbox', myRenderMailbox.render);
$('button').click(function(e) {
e.preventDefault();
var email = {
to: $('input[name=to]').val(),
subject: $('input[name=subject]').val(),
content: $('textarea[name=content]').val()
};
myNewEmail.newEmail(email);
});
});
Write a large-scale client-side app using the patterns just introduced.