7. Objects
• An unordered collection of properties
• Arrays are Objects
• Functions are Objects
• Regular Expressions are Objects
...you catch my drift
18. Object Literals
var person = {
firstName: "Leonardo",
lastName: "Borges",
age: 29
};
19. Object.create
• Specified by the ECMAScript 5th edition
• Modern browsers such as Chrome and Firefox already implement it
20. Object.create
• Specified by the ECMAScript 5th edition
• Modern browsers such as Chrome and Firefox already implement it
var anotherPerson = Object.create(person, {
age: { value: 50 }
});
anotherPerson.age; //50
21. Object.create
if (typeof Object.create !== 'function') {
Object.create = function(o) {
var F = function() {};
F.prototype = o;
return new F();
};
}
var anotherPerson = Object.create(person);
22. Functions
f(x)
• First class objects
• Linked to Function.prototype
• Can be used as constructors
31. function f(a, b, c) {
console.log(a);
console.log(b);
console.log(c);
console.log(this);
console.log(arguments);
}
f(1, 2, 3);
// 1
// 2
// 3
// DOMWindow
// [1, 2, 3]
The value of this changes depending on how the
function is called.
32. Calling functions: as methods
var person = {
firstName: "Leonardo",
lastName: "Borges",
fullName: function() {
return this.firstName + " " + this.lastName;
}
};
person.fullName();
33. Calling functions: as methods
var person = {
firstName: "Leonardo",
lastName: "Borges",
fullName: function() {
return this.firstName + " " + this.lastName;
}
};
person.fullName();
this is bound to person
37. Calling functions: using apply
Allows the value of this to be changed upon calling:
var anotherPerson = {
firstName: "Johnny",
lastName: "Cash"
};
person.fullName.apply(anotherPerson);
//Johnny Cash
38. Calling functions: using apply
Allows the value of this to be changed upon calling:
var anotherPerson = {
firstName: "Johnny",
lastName: "Cash"
};
person.fullName.apply(anotherPerson);
//Johnny Cash
this is bound to
anotherPerson
40. What does new do?
Creates a new object, obj
var obj = {};
Assigns F’s public prototype to the obj.__proto__ === F.prototype// true
obj internal prototype
this === obj// true
Binds this to obj
42. Don’t use new
• No built-in checks to prevent constructors from
being called as regular functions
• If you forget new, this will be bound to the
global object
44. new workaround
//constructor function
var F = function() {
if (!(this instanceof F)) {
return new F();
}
};
var obj = new F();
var obj = F();
//both previous statements are now equivalent
45. new workaround
//constructor function
var F = function() {
if (!(this instanceof F)) {
return new F();
}
};
var obj = new F();
var obj = F();
//both previous statements are now equivalent
You can see how cumbersome this can get
46. Closures
var Person = function(name) {
this.name = name;
return {
getName: function() {
return this.name;
}
};
};
var leo = new Person("leo");
leo.getName();
47. Closures
var Person = function(name) {
this.name = name;
return {
getName: function() {
return this.name;
}
};
};
var leo = new Person("leo");
leo.getName();
Can you guess what this line returns?
50. Closures
var Person = function(name) {
this.name = name;
return {
getName: function() {
return this.name;
}
};
};
var leo = new Person("leo");
leo.getName();
51. Closures
var Person = function(name) {
this.name = name;
return {
getName: function() {
return this.name;
Bound to the person object
}
};
};
var leo = new Person("leo");
leo.getName();
52. Closures
var Person = function(name) {
this.name = name;
return {
getName: function() {
return this.name;
Bound to the person object
}
};
};
var leo = new Person("leo"); Bound to the object literal
leo.getName();
54. Closures
var Person = function(name) {
this.name = name;
var that = this;
return {
getName: function() {
return that.name;
}
};
};
var leo = new Person("leo");
leo.getName(); // “leo”
55. Closures
var Person = function(name) {
this.name = name;
var that = this;
{
return {
getName is now a getName: function() {
closure: it closes over that return that.name;
}
};
};
var leo = new Person("leo");
leo.getName(); // “leo”
64. Weaknesses
• Lack of private members - all properties are public
• No easy access to super
• In the pseudoclassical pattern, forgetting new will break
your code
65. Weaknesses
• Lack of private members - all properties are public
• No easy access to super
• In the pseudoclassical pattern, forgetting new will break
your code
Strengths
• Using the prototype is the fastest way to create
objects when compared to closures
• In practice it will only matter if you’re creating
thousands of objects
70. Functional inheritance
var jet = function(spec) {
var that = aircraft(spec);
that.fly = function() {
return spec.name + ": Flying a jet...";
};
return that;
};
71. Functional inheritance that is now an
var jet = function(spec) {
aircraft
var that = aircraft(spec);
that.fly = function() {
return spec.name + ": Flying a jet...";
};
return that;
};
72. Functional inheritance that is now an
var jet = function(spec) {
aircraft
var that = aircraft(spec);
that.fly = function() {
return spec.name + ": Flying a jet...";
};
return that;
};
var myJet = jet({ name: "Boeing 747" });
myJet.getName(); //"Boeing 747"
myJet.fly(); //"Boeing 747: Flying a jet..."
75. Revisiting jet
var jet = function(spec) {
var that = aircraft(spec),
superFly = that.super("fly");
that.fly = function() {
return superFly() + "a frickin' jet!";
};
return that;
};
var myJet = jet({
name: "Boeing 747"
});
myJet.fly(); //"Boeing 747: Flying...a frickin' jet!"
76. Functional inheritance
Weaknesses
• Consumes more memory: every object created allocates
new function objects as necessary
• In practice it will only matter if you’re creating thousands
of objects
77. Functional inheritance
Weaknesses
• Consumes more memory: every object created allocates
new function objects as necessary
• In practice it will only matter if you’re creating thousands
of objects
Strengths
• It’s conceptually simpler than pseudoclassical inheritance
• Provides true private members
• Provides a way of working with super (albeit verbose)
• Avoids the new workaround since new isn’t used at all
81. An alternative to inheritance:
Mixins
var utils = {};
utils.enumerable = {
reduce: function(acc, f) {
for (var i = 0; i < this.length; i++) {
acc = f(acc, this[i]);
}
return acc;
}
};
82. An alternative to inheritance:
Mixins Sitck it into a module so
as to avoid clobbering
var utils = {}; the global namespace
utils.enumerable = {
reduce: function(acc, f) {
for (var i = 0; i < this.length; i++) {
acc = f(acc, this[i]);
}
return acc;
}
};
83. Mixins - implementing extends
utils.extends = function(dest,source) {
for (var prop in source) {
if (source.hasOwnProperty(prop)) {
dest[prop] = source[prop];
}
}
};
94. Partial function application
var times = function(a, b) {
return a * b;
}
var double = utils.partial(times, 2);
double(10); //20
95. Partial function application
utils.partial = function(f) {
var sourceArgs = Array.prototype.slice.apply(arguments, [1]);
return function() {
var actualArgs = Array.prototype.concat.apply(sourceArgs, arguments);
return f.apply(null, actualArgs);
};
};
96. Partial function application
utils.partial = function(f) {
var sourceArgs = Array.prototype.slice.apply(arguments, [1]);
return function() {
var actualArgs = Array.prototype.concat.apply(sourceArgs, arguments);
return f.apply(null, actualArgs);
};
};
a h
ye
* k
f *
101. Function composition
utils.comp = function() {
var functions = Array.prototype.slice.apply(arguments, [0]);
return function() {
var result = functions.reduce(arguments, function(r, f) {
return [f.apply(null, r)]
});
return result[0];
};
};
102. Function composition
utils.comp = function() {
var functions = Array.prototype.slice.apply(arguments, [0]);
return function() {
var result = functions.reduce(arguments, function(r, f) {
return [f.apply(null, r)]
});
return result[0];
};
a h
};
ye
* k
f *
103. Thankfully implements
these - and much more - for us!
106. Bottom line
• Embrace JavaScript’s true prototypal nature
• Use mixins, prototypal and functional inheritance to dispense with
classes and the new keyword
107. Bottom line
• Embrace JavaScript’s true prototypal nature
• Use mixins, prototypal and functional inheritance to dispense with
classes and the new keyword
• Use higher order functions, partial application and function
composition as elegant alternatives to promote code reuse
108. Bottom line
• Embrace JavaScript’s true prototypal nature
• Use mixins, prototypal and functional inheritance to dispense with
classes and the new keyword
• Use higher order functions, partial application and function
composition as elegant alternatives to promote code reuse
• Above all, understand each pattern’s strengths and weaknesses