KEMBAR78
Object-oriented Javascript | PDF
Object-oriented 
Javascript 
Daniel Ku (http://kjunine.net/)
Primitives and 
Objects
“Is Everything 
in JavaScript 
an object?”
WRONG!
Primitives 
» string 
» number 
» boolean 
» undefined 
» null 
Everything else is object.
“WHAT? 
Strings have 
properties and methods!”
var p = 'hello'; 
p.test = 'test'; 
console.log(p.test); // ? 
var o = new String('hello'); 
o.test = 'test'; 
console.log(o.test); // ?
var p = 'hello'; 
p.test = 'test'; 
console.log(p.test); // undefined 
var o = new String('hello'); 
o.test = 'test'; 
console.log(o.test); // test
typeof 'hello'; // string 
typeof new String('hello'); // object 
typeof 10 // number 
typeof new Number(10); // object 
typeof false; // boolean 
typeof new Boolean(true); // object 
typeof undefined; // undefined 
typeof null; // object ???
HOW 
to create an object?
Factory Functions
var createPerson = function(firstName, lastName) { 
return { 
firstName: firstName, 
lastName: lastName, 
sayHi: function() { 
return 'Hi there'; 
} 
}; 
}; 
var john = createPerson('John', 'Doe'); 
var jane = createPerson('Jane', 'Doe');
IT WORKS! BUT, 
BAD PRACTICE!
The this keyword
this 
is 
» window in global context 
» the object in an object
var name = 'Jane'; 
var greet = function() { 
return 'My name is ' + this.name; 
} 
var person = { 
name: 'John', 
greet: greet 
}; 
greet(); // ? 
person.greet(); // ?
var name = 'Jane'; 
var greet = function() { 
return 'My name is ' + this.name; 
} 
var person = { 
name: 'John', 
greet: greet 
}; 
greet(); // My name is Jane 
person.greet(); // My name is John
var requestAsync = function(url, callback) { 
var data = 10; 
callback(data); 
}; 
var requestor = { 
value: 20, 
process: function(data) { 
var sum = this.value + data; 
console.log(sum); 
}, 
request: function() { 
var url = 'http://example.com'; 
requestAsync(url, this.process); 
} 
}; 
requestor.request(); // ?
var requestAsync = function(url, callback) { 
var data = 10; 
callback(data); 
}; 
var requestor = { 
value: 20, 
process: function(data) { 
var sum = this.value + data; 
console.log(sum); 
}, 
request: function() { 
var url = 'http://example.com'; 
requestAsync(url, this.process); 
} 
}; 
requestor.request(); // NaN
Function.prototype.bind 
» reference 
» es5-shim
var requestAsync = function(url, callback) { 
var data = 10; 
callback(data); 
}; 
var requestor = { 
value: 20, 
process: function(data) { 
var sum = this.value + data; 
console.log(sum); 
}, 
request: function() { 
var url = 'http://example.com'; 
requestAsync(url, this.process.bind(this)); 
} 
}; 
requestor.request(); // 30
Constructor 
Functions
var Person = function(firstName, lastName) { 
this.firstName = firstName; 
this.lastName = lastName; 
this.sayHi = function() { 
return 'Hi~'; 
}; 
}; 
var person = new Person('John', 'Doe');
Also, 
BAD PRACTICE! 
Do like next.
var Person = function(firstName, lastName) { 
this.firstName = firstName; 
this.lastName = lastName; 
}; 
Person.prototype.sayHi = function() { 
return 'Hi~'; 
}; 
var person = new Person('John', 'Doe');
The Prototype
Object.getPrototypeOf 
» reference 
» es5-shim
person.constructor === Person; // true 
person.__proto__ === Person.prototype; // true 
Object.getPrototypeOf(person) 
=== Person.prototype; // true
person.hasOwnProperty('firstName'); // true 
person.hasOwnProperty('lastName'); // true 
person.hasOwnProperty('sayHi'); // false 
person.constructor 
.prototype 
.hasOwnProperty('sayHi'); // true
Properties and 
Property 
Descriptors
var person = {}; 
Object.defineProperty(person, 'firstName', { 
// descriptor object (data descriptor) 
value: 'John', 
writable: true 
}); 
Object.defineProperty(person, 'lastName', { 
value: 'Doe', 
writable: false 
}); 
person.firstName; // 'John' 
person.lastName; // 'Doe'
person.firstName = 'Jane'; 
person.firstName; // 'Jane' 
person.lastName = 'Dummy'; 
person.lastName; // 'Doe'
var person = {}; 
Object.defineProperties(person, { 
firstName: { 
value: 'John', 
writable: true 
}, 
lastName: { 
value: 'Doe', 
writable: true 
}, 
fullName: { 
// accessor descriptor 
get: function() { 
return this.firstName + ' ' + this.lastName; 
}, 
set: function(value) { 
var splits = value.split(' '); 
this.firstName = splits[0]; 
this.lastName = splits[1]; 
} 
} 
});
person.fullName; // 'John Doe' 
person.fullName = 'Jane Eyre' 
person.firstName; // 'Jane' 
person.lastName; // 'Eyre' 
person.fullName; // 'Jane Eyre'
var person = {}; 
Object.defineProperty(person, 'firstName', { 
value: 'John', 
enumerable: true 
}); 
Object.defineProperty(person, 'lastName', { 
value: 'Doe', 
enumerable: false 
}); 
for (var key in person) { 
console.log(key, '=>' , person[key]); 
} 
// 'firstName => John'
Object.defineProperty 
» Property Descriptors 
» Data Descriptors 
» Accessor Descriptors 
» reference 
» es5-shim
Common Keys of Descriptors 
» configurable (default: false) 
» enumerable (default: false)
Keys of Data Descriptors 
» value (default: undefined) 
» writable (default: false)
Keys of Accessor Descriptors 
» get (default: undefined) 
» set (default: undefined)
Constructors and 
the Prototype 
REVISITED
var Person = function(firstName, lastName) { 
Object.defineProperty(this, 'firstName', { 
value: firstName, 
writable: true, 
enumerable: true 
}); 
Object.defineProperty(this, 'lastName', { 
value: lastName, 
writable: true, 
enumerable: true 
}); 
};
Object.defineProperties(Person.prototype, { 
sayHi: { 
value: function() { 
return 'Hi there'; 
} 
}, 
fullName: { 
get: function() { 
return this.firstName + ' ' + this.lastName; 
}, 
enumerable: true 
} 
}); 
var person = new Person('John', 'Doe');
HOW 
to do inheritance?
Prototypical Inheritance
Object.create 
» reference 
» es5-shim
var person = { 
firstName: 'John', 
lastName: 'Doe' 
}; 
var employee = Object.create(person); 
Object.getPrototypeOf(employee) === person; // true
Object.getOwnPropertyDescriptor 
» reference 
» es5-shim
var Person = function(firstName, lastName) { 
this.firstName = firstName; 
this.lastName = lastName; 
}; 
Person.prototype.sayHi = function() { 
return 'Hi~'; 
}; 
var person = new Person('John', 'Doe'); 
Object.getOwnPropertyDescriptor(Person.prototype, 'sayHi'); 
// {value: function, writable: true, enumerable: true, configurable: true} 
Object.getOwnPropertyDescriptor(person, 'firstName'); 
// {value: "John", writable: true, enumerable: true, configurable: true}
Let's Do Inheritance
var Person = function(firstName, lastName) { 
Object.defineProperties(this, { 
firstName: { 
value: firstName, 
writable: true, 
enumerable: true 
}, 
lastName: { 
value: lastName, 
writable: true, 
enumerable: true 
} 
}); 
}; 
Object.defineProperties(Person.prototype, { 
sayHi: { 
value: function() { 
return 'Hi there'; 
} 
}, 
fullName: { 
get: function() { 
return this.firstName + ' ' + this.lastName; 
}, 
enumerable: true 
} 
});
var Employee = function(firstName, lastName, position) { 
Person.call(this, firstName, lastName); 
Object.defineProperties(this, { 
position: { 
value: position, 
writable: true, 
enumerable: true 
} 
}); 
};
Employee.prototype = Object.create(Person.prototype, { 
sayHi: { 
value: function() { 
return Person.prototype.sayHi.call(this) + ' and here'; 
} 
}, 
fullName: { 
get: function() { 
var descriptor = Object.getOwnPropertyDescriptor(Person.prototype, 'fullName'); 
return descriptor.get.call(this) + ' ' + this.position; 
}, 
enumerable: true 
}, 
constructor: { 
value: Employee 
} 
});
var employee = new Employee('John', 'Doe', 'Manager'); 
for (var key in employee) { 
console.log(key, '=>' , employee[key]); 
} 
// 'firstName => John' 
// 'lastName => Doe' 
// 'position => Manager' 
// 'fullName => John Doe Manager'
Prototypical 
Inheritance
Object.getPrototypeOf(employee) === Employee.prototype; // true 
employee.__proto__ === Employee.prototype; // true 
employee.__proto__.__proto__ === Person.prototype; // true 
employee.__proto__.__proto__.__proto__ === Object.prototype; // true 
employee.__proto__.__proto__.__proto__.__proto__ === null; // true
References 
» Object-Oriented JavaScript on Tuts+ 
» Inheritance revisited on MDN 
» ECMA-262-5 in detail by Dmitry Soshnikov
THE END

Object-oriented Javascript

  • 1.
    Object-oriented Javascript DanielKu (http://kjunine.net/)
  • 2.
  • 3.
    “Is Everything inJavaScript an object?”
  • 4.
  • 5.
    Primitives » string » number » boolean » undefined » null Everything else is object.
  • 6.
    “WHAT? Strings have properties and methods!”
  • 7.
    var p ='hello'; p.test = 'test'; console.log(p.test); // ? var o = new String('hello'); o.test = 'test'; console.log(o.test); // ?
  • 8.
    var p ='hello'; p.test = 'test'; console.log(p.test); // undefined var o = new String('hello'); o.test = 'test'; console.log(o.test); // test
  • 9.
    typeof 'hello'; //string typeof new String('hello'); // object typeof 10 // number typeof new Number(10); // object typeof false; // boolean typeof new Boolean(true); // object typeof undefined; // undefined typeof null; // object ???
  • 10.
    HOW to createan object?
  • 11.
  • 12.
    var createPerson =function(firstName, lastName) { return { firstName: firstName, lastName: lastName, sayHi: function() { return 'Hi there'; } }; }; var john = createPerson('John', 'Doe'); var jane = createPerson('Jane', 'Doe');
  • 13.
    IT WORKS! BUT, BAD PRACTICE!
  • 14.
  • 15.
    this is »window in global context » the object in an object
  • 16.
    var name ='Jane'; var greet = function() { return 'My name is ' + this.name; } var person = { name: 'John', greet: greet }; greet(); // ? person.greet(); // ?
  • 17.
    var name ='Jane'; var greet = function() { return 'My name is ' + this.name; } var person = { name: 'John', greet: greet }; greet(); // My name is Jane person.greet(); // My name is John
  • 18.
    var requestAsync =function(url, callback) { var data = 10; callback(data); }; var requestor = { value: 20, process: function(data) { var sum = this.value + data; console.log(sum); }, request: function() { var url = 'http://example.com'; requestAsync(url, this.process); } }; requestor.request(); // ?
  • 19.
    var requestAsync =function(url, callback) { var data = 10; callback(data); }; var requestor = { value: 20, process: function(data) { var sum = this.value + data; console.log(sum); }, request: function() { var url = 'http://example.com'; requestAsync(url, this.process); } }; requestor.request(); // NaN
  • 20.
  • 21.
    var requestAsync =function(url, callback) { var data = 10; callback(data); }; var requestor = { value: 20, process: function(data) { var sum = this.value + data; console.log(sum); }, request: function() { var url = 'http://example.com'; requestAsync(url, this.process.bind(this)); } }; requestor.request(); // 30
  • 22.
  • 23.
    var Person =function(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; this.sayHi = function() { return 'Hi~'; }; }; var person = new Person('John', 'Doe');
  • 24.
    Also, BAD PRACTICE! Do like next.
  • 25.
    var Person =function(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; }; Person.prototype.sayHi = function() { return 'Hi~'; }; var person = new Person('John', 'Doe');
  • 26.
  • 29.
  • 30.
    person.constructor === Person;// true person.__proto__ === Person.prototype; // true Object.getPrototypeOf(person) === Person.prototype; // true
  • 31.
    person.hasOwnProperty('firstName'); // true person.hasOwnProperty('lastName'); // true person.hasOwnProperty('sayHi'); // false person.constructor .prototype .hasOwnProperty('sayHi'); // true
  • 32.
  • 33.
    var person ={}; Object.defineProperty(person, 'firstName', { // descriptor object (data descriptor) value: 'John', writable: true }); Object.defineProperty(person, 'lastName', { value: 'Doe', writable: false }); person.firstName; // 'John' person.lastName; // 'Doe'
  • 34.
    person.firstName = 'Jane'; person.firstName; // 'Jane' person.lastName = 'Dummy'; person.lastName; // 'Doe'
  • 35.
    var person ={}; Object.defineProperties(person, { firstName: { value: 'John', writable: true }, lastName: { value: 'Doe', writable: true }, fullName: { // accessor descriptor get: function() { return this.firstName + ' ' + this.lastName; }, set: function(value) { var splits = value.split(' '); this.firstName = splits[0]; this.lastName = splits[1]; } } });
  • 36.
    person.fullName; // 'JohnDoe' person.fullName = 'Jane Eyre' person.firstName; // 'Jane' person.lastName; // 'Eyre' person.fullName; // 'Jane Eyre'
  • 37.
    var person ={}; Object.defineProperty(person, 'firstName', { value: 'John', enumerable: true }); Object.defineProperty(person, 'lastName', { value: 'Doe', enumerable: false }); for (var key in person) { console.log(key, '=>' , person[key]); } // 'firstName => John'
  • 38.
    Object.defineProperty » PropertyDescriptors » Data Descriptors » Accessor Descriptors » reference » es5-shim
  • 39.
    Common Keys ofDescriptors » configurable (default: false) » enumerable (default: false)
  • 40.
    Keys of DataDescriptors » value (default: undefined) » writable (default: false)
  • 41.
    Keys of AccessorDescriptors » get (default: undefined) » set (default: undefined)
  • 42.
    Constructors and thePrototype REVISITED
  • 43.
    var Person =function(firstName, lastName) { Object.defineProperty(this, 'firstName', { value: firstName, writable: true, enumerable: true }); Object.defineProperty(this, 'lastName', { value: lastName, writable: true, enumerable: true }); };
  • 44.
    Object.defineProperties(Person.prototype, { sayHi:{ value: function() { return 'Hi there'; } }, fullName: { get: function() { return this.firstName + ' ' + this.lastName; }, enumerable: true } }); var person = new Person('John', 'Doe');
  • 45.
    HOW to doinheritance?
  • 46.
  • 47.
  • 48.
    var person ={ firstName: 'John', lastName: 'Doe' }; var employee = Object.create(person); Object.getPrototypeOf(employee) === person; // true
  • 49.
  • 50.
    var Person =function(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; }; Person.prototype.sayHi = function() { return 'Hi~'; }; var person = new Person('John', 'Doe'); Object.getOwnPropertyDescriptor(Person.prototype, 'sayHi'); // {value: function, writable: true, enumerable: true, configurable: true} Object.getOwnPropertyDescriptor(person, 'firstName'); // {value: "John", writable: true, enumerable: true, configurable: true}
  • 51.
  • 52.
    var Person =function(firstName, lastName) { Object.defineProperties(this, { firstName: { value: firstName, writable: true, enumerable: true }, lastName: { value: lastName, writable: true, enumerable: true } }); }; Object.defineProperties(Person.prototype, { sayHi: { value: function() { return 'Hi there'; } }, fullName: { get: function() { return this.firstName + ' ' + this.lastName; }, enumerable: true } });
  • 53.
    var Employee =function(firstName, lastName, position) { Person.call(this, firstName, lastName); Object.defineProperties(this, { position: { value: position, writable: true, enumerable: true } }); };
  • 54.
    Employee.prototype = Object.create(Person.prototype,{ sayHi: { value: function() { return Person.prototype.sayHi.call(this) + ' and here'; } }, fullName: { get: function() { var descriptor = Object.getOwnPropertyDescriptor(Person.prototype, 'fullName'); return descriptor.get.call(this) + ' ' + this.position; }, enumerable: true }, constructor: { value: Employee } });
  • 55.
    var employee =new Employee('John', 'Doe', 'Manager'); for (var key in employee) { console.log(key, '=>' , employee[key]); } // 'firstName => John' // 'lastName => Doe' // 'position => Manager' // 'fullName => John Doe Manager'
  • 56.
  • 58.
    Object.getPrototypeOf(employee) === Employee.prototype;// true employee.__proto__ === Employee.prototype; // true employee.__proto__.__proto__ === Person.prototype; // true employee.__proto__.__proto__.__proto__ === Object.prototype; // true employee.__proto__.__proto__.__proto__.__proto__ === null; // true
  • 59.
    References » Object-OrientedJavaScript on Tuts+ » Inheritance revisited on MDN » ECMA-262-5 in detail by Dmitry Soshnikov
  • 60.