Upload
andy-primawan
View
30
Download
0
Tags:
Embed Size (px)
DESCRIPTION
Slide mata kuliah Pemrograman Berorientasi Objek : Javascript Properties
Citation preview
5/13/2009 1
IF2032Pemrograman Berorientasi ObjekJavascript - Prototype
Achmad Imam Kistijantoro ([email protected])Yani Widyani ([email protected])Februari 2009Informatika – STEI – ITB
Sumber: Object-Oriented JavaScript, Create scalable, reusable high-quality JavaScript applications, and libraries, Stoyan Stefanov, 2008
prototype Property
Property of the function objects created as soon as you define the function
its initial value is an empty object
>>> function foo(a, b){return a * b;}
>>> typeof foo.prototype
"object“
You can augment this empty object with properties and methods They won't have any effect of the foo() function itself
they'll only be used when you use foo() as a constructor
Adding methods and properties
function Gadget(name, color) { this.name = name; this.color = color; this.whatAreYou = function(){
return 'I am a ' + this.color + ' ' + this.name; }
}
Adding methods and properties:Gadget.prototype.price = 100;Gadget.prototype.rating = 3;Gadget.prototype.getInfo = function() {
return 'Rating: ' + this.rating + ', price: ' + this.price;};
Adding methods and properties to the prototype property of the constructor function is another way to add functionality to the objects this constructor produces
Adding methods and properties (2)
Gadget.prototype = { price: 100, rating: 3, getInfo: function() {
return 'Rating: ' + this.rating + ', price: ' + this.price; }
};
Using the Prototype’s methods and properties
>>> var newtoy = new Gadget('webcam', 'black');>>> newtoy.name; "webcam“
>>> newtoy.color; "black“
>>> newtoy.whatAreYou(); "I am a black webcam"
>>> newtoy.price; 100
>>> newtoy.rating; 3
>>> newtoy.getInfo(); "Rating: 3, price: 100“
Using the Prototype’s methods and properties (2)
Gadget.prototype.get = function(what) { return this[what];};
Even though newtoy was created before the get() method was defined, newtoy will still have access to the new method:
>>> newtoy.get('price'); 100>>> newtoy.get('color'); "black"
Own vs prototype properties
>>> var newtoy = new Gadget('webcam', 'black');
When you try to access a property of newtoy, say newtoy.name the JavaScript engine will look through all of the properties of the object searching for one called name and, if it finds it, will return its value.>>> newtoy.name "webcam“
What if you try to access the rating property, the JavaScript engine will examine all of the properties of newtoy and will not find the one called rating.
The script engine will identify the prototype of the constructor function used to create this object
If the property is found in the prototype, this property is used.>>> newtoy.rating 3
Own vs prototype properties (2)
Every object has a constructor
The prototype is an object, so it must have a constructor too, which in turn has a prototype>>> newtoy.constructor.prototype.constructor
Gadget(name, color)
>>> newtoy.constructor.prototype.constructor.prototype
Object price=100 rating=3
prototype chain
Overwriting prototype’s property with own property If the own property has the same name with the prototype’s property, the own
property takes precedence over the prototype'sfunction Gadget(name) {
this.name = name;}Gadget.prototype.name = 'foo'; "foo"
Creating a new object and accessing its name property gives you the object's own name property
>>> var toy = new Gadget('camera');>>> toy.name; "camera"
If you delete this property, the prototype's property with the same name "shines through":
>>> delete toy.name; true>>> toy.name; "foo"
Enumerating properties
function Gadget(name, color) { this.name = name; this.color = color; this.someMethod = function(){return 1;}
}Gadget.prototype.price = 100;Gadget.prototype.rating = 3;
for (var prop in newtoy) { console.log(prop + ' = ' + newtoy[prop]);
}
name = webcam color = black someMethod = function () { return 1; } price = 100 rating = 3
Enumerating properties (2)
Notes: Not all properties show up in a for-in loop. For example, the
length (for arrays) and constructor properties will not show up. The properties that do show up are called enumerable. You can check with the propertyIsEnumerable() method
Prototypes that come through the prototype chain will also show up, provided they are enumerable You can check if a property is an own property using the
hasOwnProperty() method
propertyIsEnumerable() will return false for all of the prototype's properties, even those that are enumerable and will show up in the for-in loop
hasOwnProperty()
>>> newtoy.hasOwnProperty('name') true>>> newtoy.hasOwnProperty('price') False
for (var prop in newtoy) { if (newtoy.hasOwnProperty(prop)) {
console.log(prop + '=' + newtoy[prop]); }
}
The result:
name=webcam color=black someMethod=function () { return 1; }
propertyIsEnumerable()
>>> newtoy.propertyIsEnumerable('name') true
Most built-in properties and methods are not enumerable:>>> newtoy.propertyIsEnumerable('constructor') false
Any properties coming down the prototype chain are not enumerable:>>> newtoy.propertyIsEnumerable('price') false
However, that such properties are enumerable if you reach the objectcontained in the prototype and invoke its propertyIsEnumerable().>>> newtoy.constructor.prototype.propertyIsEnumerable('price') true
isPrototypeOf()
tells you whether that specific object is used as a prototype of another objectvar monkey = {
hair: true, feeds: 'bananas', breathes: 'air'
};
function Human(name) { this.name = name;
} Human.prototype = monkey;
>>> var george = new Human('George'); >>> monkey.isPrototypeOf(george) true
The secret __proto__ link
var developer = new Human();developer.feeds = 'pizza';developer.hacks = 'JavaScript';
>>> developer.constructor = 'junk' "junk"
It seems like the prototype is now all messed up:>>> typeof developer.constructor.prototype "undefined"
...but it isn't, because the developer still breathes "air":>>> developer.breathes ”air”
The secret __proto__ link (2)
The secret link to the prototype still exists The secret link is exposed in Firefox as the __proto__
property
>>> developer.__proto__ Object feeds=bananas breathes=air
You can use this secret property for learning purposes but it's not a good idea to use it in your real scripts, because it does not exist in Internet Explorer, so your scripts won't be portable __proto__ is a property of the instances prototype is a property of the constructor functions
Augmenting built-in objects
The built-in objects such as the constructor functions Array, String, and even Object, and Function can be augmented through their prototypes
which means that you can, for example, add new methods to the Array prototype and in this way make them available to all arrays
Augmenting built-in objects (2)
Array.prototype.inArray = function(needle) { for (var i = 0, len = this.length; i < len; i++) {
if (this[i] === needle) { return true;
} } return false;
}
>>> var a = ['red', 'green', 'blue'];>>> a.inArray('red'); True
String.prototype.reverse = function() { return Array.prototype.reverse.apply(this.split('')).join('');
}
>>> "Stoyan".reverse(); "nayotS"
Augmenting built-in objects (3)
If you decide to augment the prototype of built-in objects with a new property, do check for existence of the new property first.
if (!String.prototype.reverse) {
String.prototype.reverse = function() {
return Array.prototype.reverse.apply(this.split('')).join('');
}
}
Notes
two interesting behaviors to consider when dealing with prototypes:
The prototype chain is live with the exception of when you completely replace the prototype object
prototype.constructor is not reliable
>>> function Dog(){this.tail = true;}>>> var benji = new Dog();>>> var rusty = new Dog();
>>> Dog.prototype.say = function(){return 'Woof!';}>>> benji.say(); "Woof!“
>>> Dog.prototype = {paws: 4, hair: true};>>> typeof benji.paws "undefined">>> benji.say() "Woof!"
>>> var lucy = new Dog();>>> lucy.say() TypeError: lucy.say is not a function>>> lucy.paws 4
The secret __proto__ link points to the new prototype object
The following would have fixed all of the unexpected behavior described above:>>> Dog.prototype = {paws: 4, hair: true};>>> Dog.prototype.constructor = Dog;
When you overwrite the prototype, it is a good idea to reset the constructor property