Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Write code and diagrams for object-graphs-2.
- Loading branch information
1 parent
70a4301
commit bf25e9d
Showing
7 changed files
with
286 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
Title: Learning Javascript with Object Graphs (Part II) | ||
Author: Tim Caswell | ||
Date: Wed Oct 06 2010 09:31:21 GMT-0700 (PDT) | ||
Node: v0.2.3 | ||
|
||
The first article using graphs to describe JavaScript semantics was so popular that I've decided to try the technique with some more advanced ideas. In this article I'll explain three common techniques for creating objects. They are constructor with prototype, pure prototypal, and object factory. | ||
|
||
My goal is that this will help people understand the strengths and weaknesses of each technique and understand what's really going on. | ||
|
||
## Classical JavaScript Constructors | ||
|
||
<object-graphs-2/classical.js#rectangle> | ||
|
||
<object-graphs-2/classical.js#square> | ||
|
||
<object-graphs-2/classical.js#test*> | ||
|
||
![classical](object-graphs-2/classical.dot) | ||
|
||
<br style="clear:left"/> | ||
|
||
## Pure Prototypal Objects | ||
|
||
<object-graphs-2/prototypal.js#rectangle> | ||
|
||
<object-graphs-2/prototypal.js#square> | ||
|
||
<object-graphs-2/prototypal.js#test*> | ||
|
||
![classical](object-graphs-2/prototypal.dot) | ||
|
||
<br style="clear:left"/> | ||
|
||
## Object Factories | ||
|
||
<object-graphs-2/factory.js#controller> | ||
|
||
<object-graphs-2/factory.js#usage> | ||
|
||
// Output | ||
View now has 5 | ||
View now has 6 | ||
View now has 5 | ||
Saving value 5 somewhere | ||
Now hiding view | ||
|
||
|
||
![classical](object-graphs-2/factory.dot) | ||
|
||
<br style="clear:left"/> | ||
|
||
## Conclusion | ||
|
||
There is so much more I want to explore, but I like to keep these articles somewhat short and bite-size. If there is demand, I'll write a part three explaining how to do ruby-style mixins and other advanced topics. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
digraph finite_state_machine { | ||
size="8.3,8" | ||
rankdir = "LR" | ||
|
||
/* Execution Contexts */ | ||
node [shape=Mrecord, fillcolor=beige, style=filled]; | ||
top [label="<__proto__>[ Scope ]|<Rectangle>Rectangle|<rect>rect|<Square>Square|<sqr>sqr"]; | ||
|
||
/* Normal Objects */ | ||
node [shape = Mrecord, fillcolor=lightskyblue, style=filled]; | ||
ob_RectProto [label = "<__proto__>[ Object ]|<constructor>constructor|<getArea>getArea|<getPerimeter>getPerimeter|<toString>toString"]; | ||
ob_SquareProto [label = "<__proto__>[ Object ]|<constructor>constructor|<getPerimeter>getPerimeter"]; | ||
ob_rect [label = "<__proto__>[ Object ]|<width>width=6|<height>height=4"]; | ||
ob_sqr [label = "<__proto__>[ Object ]|<width>width=5|<height>height=5"]; | ||
|
||
/* Function Objects */ | ||
node [shape = Mrecord, fillcolor=orange, style=filled]; | ||
fn_Rectangle [label="<__proto__>[Rectangle(width, height)]|\{this.width = width…\}|<prototype>prototype"]; | ||
fn_Square [label="<__proto__>[Square(width)]|\{this.width = width…\}|<prototype>prototype"]; | ||
fn_getArea [label="<__proto__>[getArea()]|\{return this.width * this.height\}"]; | ||
fn_getPerimeter [label="<__proto__>[getPerimeter()]|\{return 2 * (this.width + this.height)\}"]; | ||
fn_toString [label="<__proto__>[toString()]|\{return this.constructor.name…\}"]; | ||
fn_getPerimeter2 [label="<__proto__>[getPerimeter()]|\{return 4 * this.width\}"]; | ||
|
||
/* References */ | ||
top:Rectangle -> fn_Rectangle:__proto__; | ||
top:Square -> fn_Square:__proto__; | ||
top:rect -> ob_rect:__proto__; | ||
top:sqr -> ob_sqr:__proto__; | ||
fn_Rectangle:prototype -> ob_RectProto:__proto__; | ||
fn_Square:prototype -> ob_SquareProto:__proto__; | ||
ob_RectProto:constructor -> fn_Rectangle:__proto__; | ||
ob_RectProto:getArea -> fn_getArea:__proto__; | ||
ob_RectProto:getPerimeter -> fn_getPerimeter:__proto__; | ||
ob_RectProto:toString -> fn_toString:__proto__; | ||
ob_SquareProto:constructor -> fn_Square:__proto__; | ||
ob_SquareProto:getPerimeter -> fn_getPerimeter2:__proto__; | ||
|
||
/* Inheritance Chains */ | ||
edge [style=dashed] | ||
ob_rect:__proto__ -> ob_RectProto:__proto__; | ||
ob_sqr:__proto__ -> ob_SquareProto:__proto__; | ||
ob_SquareProto:__proto__ -> ob_RectProto:__proto__; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
//rectangle | ||
function Rectangle(width, height) { | ||
this.width = width; | ||
this.height = height; | ||
} | ||
Rectangle.prototype.getArea = function getArea() { | ||
return this.width * this.height; | ||
}; | ||
Rectangle.prototype.getPerimeter = function getPerimeter() { | ||
return 2 * (this.width + this.height); | ||
}; | ||
Rectangle.prototype.toString = function toString() { | ||
return this.constructor.name + " a=" + this.getArea() + " p=" + this.getPerimeter(); | ||
}; | ||
//square | ||
function Square(side) { | ||
this.width = side; | ||
this.height = side; | ||
} | ||
Square.prototype.__proto__ = Rectangle.prototype; | ||
Square.prototype.getPerimeter = function getPerimeter() { | ||
return this.width * 4; | ||
}; | ||
//test | ||
var rect = new Rectangle(6, 4); | ||
var sqr = new Square(5); | ||
console.log(rect.toString()) | ||
console.log(sqr.toString()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
digraph finite_state_machine { | ||
size="8.3,8" | ||
rankdir = "LR" | ||
|
||
/* Execution Contexts */ | ||
node [shape=Mrecord, fillcolor=beige, style=filled]; | ||
top [label="<__proto__>[ Scope ]|<Controller>Controller|<on>on"]; | ||
closure [label="<__proto__>[ Scope ]|<view>view|<model>model"]; | ||
|
||
/* Normal Objects */ | ||
node [shape = Mrecord, fillcolor=lightskyblue, style=filled]; | ||
ob_view [label="<__proto__>[ Object ]|<update>update|<close>close"] | ||
ob_model [label="<__proto__>[ Object ]|<value>value=5|<save>save"]; | ||
ob_on [label="<__proto__>[ Object ]|<up>up|<down>down|<save>save"]; | ||
|
||
/* Function Objects */ | ||
node [shape = Mrecord, fillcolor=orange, style=filled]; | ||
fn_update [label="<__proto__>[update(value)]|\{ console.log(…) \}|<__scope__>[scope]"] | ||
fn_close [label="<__proto__>[close()]|\{ console.log(…) \}|<__scope__>[scope]"] | ||
fn_save [label="<__proto__>[save()]|\{ console.log(…) \}"]; | ||
fn_Controller [label="<__proto__>[Controller(model, view)]|\{ view.update(model.value) … \}"] | ||
fn_onUp [label="<__proto__>[onUp()]|\{ model.value++ … \}|<__scope__>[scope]"]; | ||
fn_onDown [label="<__proto__>[onDown()]|\{ model.value-- … \}|<__scope__>[scope]"]; | ||
fn_onSave [label="<__proto__>[onSave()]|\{ model.save() … \}|<__scope__>[scope]"]; | ||
|
||
/* References */ | ||
ob_view:update -> fn_update:__proto__; | ||
ob_view:close -> fn_close:__proto__; | ||
ob_model:save -> fn_save:__proto__; | ||
top:Controller -> fn_Controller:__proto__; | ||
top:on -> ob_on; | ||
ob_on:up -> fn_onUp:__proto__; | ||
ob_on:down -> fn_onDown:__proto__; | ||
ob_on:save -> fn_onSave:__proto__; | ||
fn_onUp:__scope__ -> closure; | ||
fn_onDown:__scope__ -> closure; | ||
fn_onSave:__scope__ -> closure; | ||
closure:view -> ob_view:__proto__; | ||
closure:model -> ob_model:__proto__; | ||
|
||
/* Inheritance Chains */ | ||
edge [style=dashed] | ||
closure -> top:__proto__; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
//controller | ||
function Controller(model, view) { | ||
view.update(model.value); | ||
return { | ||
up: function onUp(evt) { | ||
model.value++; | ||
view.update(model.value); | ||
}, | ||
down: function onDown(evt) { | ||
model.value--; | ||
view.update(model.value); | ||
}, | ||
save: function onSave(evt) { | ||
model.save(); | ||
view.close(); | ||
} | ||
}; | ||
} | ||
//usage | ||
var on = Controller( | ||
// Inline a mock model | ||
{ | ||
value: 5, | ||
save: function save() { | ||
console.log("Saving value " + this.value + " somewhere"); | ||
} | ||
}, | ||
// Inline a mock view | ||
{ | ||
update: function update(newValue) { | ||
console.log("View now has " + newValue); | ||
}, | ||
close: function close() { | ||
console.log("Now hiding view"); | ||
} | ||
} | ||
); | ||
setTimeout(on.up, 100); | ||
setTimeout(on.down, 200); | ||
setTimeout(on.save, 300); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
digraph finite_state_machine { | ||
size="8.3,5" | ||
rankdir = "LR" | ||
|
||
|
||
/* Execution Contexts */ | ||
node [shape=Mrecord, fillcolor=beige, style=filled]; | ||
top [label="<__proto__>[ Scope ]|<Rectangle>Rectangle|<rect>rect|<Square>Square|<sqr>sqr"]; | ||
|
||
/* Normal Objects */ | ||
node [shape = Mrecord, fillcolor=lightskyblue, style=filled]; | ||
ob_Rectangle [label = "<__proto__>[ Object ]|<name>name=\"Rectangle\"|<getArea>getArea|<getPerimeter>getPerimeter|<toString>toString"]; | ||
ob_Square [label = "<__proto__>[ Object ]|<name>name=\"Square\"|<getArea>getArea|<getPerimeter>getPerimeter"]; | ||
ob_rect [label = "<__proto__>[ Object ]|<width>width=6|<height>height=4"]; | ||
ob_sqr [label = "<__proto__>[ Object ]|<width>width=5"]; | ||
|
||
/* Function Objects */ | ||
node [shape = Mrecord, fillcolor=orange, style=filled]; | ||
fn_getArea [label="<__proto__>[getArea()]|\{return this.width * this.height\}"]; | ||
fn_getPerimeter [label="<__proto__>[getPerimeter()]|\{return 2 * (this.width + this.height)\}"]; | ||
fn_toString [label="<__proto__>[toString()]|\{return this.name + \" a=\" + …\}"]; | ||
fn_getArea2 [label="<__proto__>[getArea()]|\{return this.width * this.width\}"]; | ||
fn_getPerimeter2 [label="<__proto__>[getPerimeter()]|\{return 4 * this.width\}"]; | ||
|
||
/* References */ | ||
top:Rectangle -> ob_Rectangle:__proto__; | ||
top:Square -> ob_Square:__proto__; | ||
top:rect -> ob_rect:__proto__; | ||
top:sqr -> ob_sqr:__proto__; | ||
ob_Rectangle:getArea -> fn_getArea:__proto__; | ||
ob_Rectangle:getPerimeter -> fn_getPerimeter:__proto__; | ||
ob_Rectangle:toString -> fn_toString:__proto__; | ||
ob_Square:getArea -> fn_getArea2:__proto__; | ||
ob_Square:getPerimeter -> fn_getPerimeter2:__proto__; | ||
|
||
/* Inheritance Chains */ | ||
edge [style=dashed] | ||
ob_rect:__proto__ -> ob_Rectangle:__proto__; | ||
ob_sqr:__proto__ -> ob_Square:__proto__; | ||
ob_Square:__proto__ -> ob_Rectangle:__proto__; | ||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
//rectangle | ||
var Rectangle = { | ||
name: "Rectangle", | ||
getArea: function getArea() { | ||
return this.width * this.height; | ||
}, | ||
getPerimeter: function getPerimeter() { | ||
return 2 * (this.width + this.height); | ||
}, | ||
toString: function toString() { | ||
return this.name + " a=" + this.getArea() + " p=" + this.getPerimeter(); | ||
} | ||
}; | ||
//square | ||
var Square = { | ||
name: "Square", | ||
getArea: function getArea() { | ||
return this.width * this.width; | ||
}, | ||
getPerimeter: function getPerimeter() { | ||
return this.width * 4; | ||
}, | ||
}; | ||
Square.__proto__ = Rectangle; | ||
//test | ||
var rect = Object.create(Rectangle); | ||
rect.width = 6; | ||
rect.height = 4; | ||
var square = Object.create(Square); | ||
square.width = 5; | ||
console.log(rect.toString()); | ||
console.log(square.toString()); |