Weitere ähnliche Inhalte Ähnlich wie Say It With Javascript (20) Mehr von Giovanni Scerra ☃ (6) Kürzlich hochgeladen (20) Say It With Javascript2. Objects & C.
//Creating objects
var myObj1 = {};
var myObj2 = new Object();
//Creating arrays
var myArr1 = [];
var myArr2 = new Array();
var myArr3 = [1, "a"];
myArr3.length == 2 //true
//Exploiting objects
typeof myObj1 //"object"
myObj1 instanceof Object //true
myObj1.constructor //function Object() { [native
code] }
//Exploiting arrays
typeof myArr1 //"object"
myArr1 instanceof Array //true (within same frame)
myArr1 instanceof Object //true
myArr1.constructor //function Array() { [native code]
}
//Adding properties
myObj1.x = 5;
myObj2["x"] = 5;
myObj2.double = function(x) { return x*2; }
myObj1["x"] == myObj2.x //true
myObj2.x //5
myArr1.x = "test";
myArr1["y"] = "test";
myArr1.y == myArr1["x"] //true
//Test
var testArr = [];
testArr["x"] = "element x";
testArr["y"] = "element 0";
testArr.length //???
//Literals
var person = {
name: "giovanni",
age: 41,
rejuvenate: function() {
this.age--;
}
}
//The proto chain
var developer = {
salary: 999999
}
//Using Object.create
var developer = Object.create(person);
developer.salary = 999999;
developer.name //"giovanni"
developer.__proto__ == person; //true
//Test
person.age = 10;
developer.age //???
3. Functions & C.
//Defining functions
function sayHello1() {
console.log("Hi there!");
}
var sayHello2 = function() {
console.log("Hi there!");
}
//Test
sayHello1.name //??
sayHello2.name //??
typeof sayHello1 //function
sayHello1 instanceof Object //true
sayHello1.constructor //function Function() {…}
var fn = new Function("","console.log('Hi there!')");
//Calling function
var sayHelloTo = function sayHelloTo(name) {
return this.greeting + " " + name;
}
sayHelloTo("Giovanni"); //"undefined Giovanni"
window.greeting = "Good morning"
sayHelloTo("Giovanni"); //"Good morning Giovanni"
//Calling functions within a context
var evening = { greeting: "Good evening"};
//"Good evening Giovanni"
sayHelloTo.apply(evening, ["Giovanni"]);
sayHelloTo.call(evening, "Giovanni");
var urbanGreeter = {
greeting: "Sup",
greet: sayHelloTo
}
urbanGreeter.greet("Giovanni") //"Sup Giovanni"
//Test
//What is this function doing?
function bind(fnContext, fn) {
return function() {
return fn.apply(fnContext, arguments);
}
}
//Test
function reverseName() {
return this.name.split("").reverse().join("");
}
var r = bind({name: "giovanni"}, reverseName);
r(); //??
4. Closures
//Defining closures
function counter(startAt){
var count = startAt;
return function(){
console.log(++count)
};
}
var next = counter(0);
next(); //1
next(); //2
next(); //3
//Closures with input parameters
var quo = function (status) {
return {
get_status: function ( ) {
return status;
}
};
};
var myQuo = quo("active");
myQuo.get_status(); //"active"
//Test
var handlers = [];
for (var i = 0; i < 10; i += 1) {
handlers.push(
function() { return i; }
);
};
handlers[2](); //???
handlers[6](); //???
//Test
var handlers = [];
for (var i = 0; i < 10; i += 1) {
handlers.push(
function(i) {
return function() { return i;};
}(i)
);
};
var index = handlers.length;
while(index) console.log(handlers[--index]()); //???
//Using closures for encapsulation
function buildProduct() {
var productID = 999;
return {
getID: function () {
return productID;
},
setID: function (theNewID) {
productID = theNewID;
}
}
}
var product = buildProduct();
product.getID(); // 999
product.setID(478);
product.getID(); // 478
//Test
var shortCut = product.getID;
shortCut(); //???
5. Inheritance
//Inheritance with the ‘new’ operator
//constructor
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.getName = function(){
return this.name;
};
Person.prototype.getAge = function(){
return this.age;
};
Person.prototype.title = "Mr.";
var badPerson = Person("Max",30);
badPerson == undefined; //true
window.name == "Max"; //true
var goodPerson1 = new Person("Giovanni",41);
var goodPerson2 = new Person("John",30);
goodPerson1.getName() == "Giovanni"; //true
goodPerson2.getAge() == "30"; //true
goodPerson2.title = "Mr."; //true
//Test
goodPerson2.age = 31;
goodPerson2.title = "Dr.";
console.log(goodPerson1.age); //??
console.log(goodPerson1.title); //??
//inheritance chains
function Worker(name, age, profession, salary) {
Person.call(this,name,age);
this.profession = profession;
this.salary = salary;
}
Worker.prototype = new Person();
//Added for legacy code compatibility
Worker.prototype.constructor = Worker;
Worker.prototype.fire = function() {
this.profession = "unemployed";
}
Worker.prototype.giveBigRaise = function() {
this.salary += 10000;
}
var w1 = new Worker("Giovanni", 41, "developer", 0);
var w2 = new Worker("John", 43, "developer", 0);
//Test
w1.giveBigRaise();
w1.salary; //??
w2.salary; //??
w1.getAge(); //??
w1.title == "Mr."; //??
w1 instance of Worker; //??
W2 instance of Worker; //??
w1 instance of Person; //??
w1 instance of Object; //??
6. //Extending native types – forEach polyfill
if (!Array.prototype.forEach) {
Array.prototype.forEach = function (fn, scope) {
for (var i = 0, l = this.length; i < l; ++i) {
if (i in this) {
fn.call(scope, this[i], i, this);
}
}
};
}
['a','b','c'].forEach(
function(elm, index, ctx) {
console.log(index +'. ' + elm);
},
window
);
//Inheritance with Object.create
var myMammal = {
name : 'Herb the Mammal',
get_name : function ( ) {
return this.name;
},
says : function ( ) {
return this.saying || '';
}
};
var myCat1 = createCat('Henrietta');
var myCat2 = createCat('Rocky');
function createCat(name) {
var obj = Object.create(myMammal);
obj.name = name;
obj.saying = 'meow';
obj.purr = function (n) {
return 'r-r-r-r-r';
};
obj.get_name = function ( ) {
return this.says( ) + ' ' + this.name + ' ';
};
return obj;
}
myCat2.get_name(); //??
myMammal.bloodTemperature = 'warm’;
myCat1.bloodTemperature; //??
7. //Functional Inheritance
function base(spec) {
var that = {};
that.name = spec.name;
return that; // Return the object
}
function child(spec) {
var that = base(spec);
that.sayHello = function() {
return 'Hello, I'm ' + that.name;
};
return that; // Return it
}
// Usage
var object = child({ name: 'a functional object' });
console.log(object.sayHello());
//Mixins
var asButton = function() {
this.hover = function() {
console.log('hover handler');
};
this.press = function() {
console.log('press handler');
};
this.fire = function() {
return this.action();
};
return this;
};
var asCircle = function() {
this.area = function() {
return Math.PI * this.radius * this.radius;
};
this.grow = function() {
this.radius++;
};
this.shrink = function() {
this.radius--;
};
return this;
};
var RoundButton = function(radius, label, action) {
this.radius = radius;
this.label = label;
this.action = action;
};
asButton.call(RoundButton.prototype);
asCircle.call(RoundButton.prototype);
var button1 = new RoundButton(4, 'yes!',
function() {return 'you said yes!';}
);
button1.fire(); //'you said yes!'
8. Namespaces & Temp. Scope
//Creating namespaces manually
var afsi = afsi || {};
afsi.utilities = myApp.utilities || {};
afsi.utilities.sayHello = function(name) {
return "Hi " + name;
}
//A namespace utility
var afsi = afsi || {};
afsi.namespace = function namespace(namespaceString) {
var parts = namespaceString.split('.'),
parent = window,
currentPart = '';
for(var i = 0, length = parts.length; i < length; i++) {
currentPart = parts[i];
parent[currentPart] = parent[currentPart] || {};
parent = parent[currentPart];
}
}
//Defining and using a namespace
afsi.namespace("afsi.utilities");
var afsi.utilities.sayHello = function(name) {
return "Hi " + name;
}
//‘Wrapping’ techniques
(function(){
var myLib = window.myLib = function(){
// Initialize
};
// ...
})();
---------------------------------------------
var myLib = (function(){
function myLib(){
// Initialize
}
// ...
return myLib;
})();
---------------------------------------------
(function( window, document, NS, undefined ){
NS.variableName = "string value";
NS.methodName = function() {};
// ...
}(window,
window.document,
(window.NS = window.NS || {})
)
);
---------------------------------------------
function MyScript(){}
(function() {
var THIS = this;
function defined(x) {
alert(THIS); //points to MyScript()
}
// ...
}).apply(MyScript);
9. Module Pattern – (singleton, revealing)
var afsi = afsi || {};
var afsi.calculator = (function () {
var _m = 0;
function _add(n1,n2) {
return n1+n2;
}
function _substract(n1,n2) {
return n1-n2;
}
function _setM(m) {
return _m = m;
}
function _getM() {
return _m;
}
return {
add: _add,
substract: _substract,
setM: _setM,
getM: _getM
};
}());
10. Module Pattern – constructor (OOP)
var afsi = afsi || {};
afsi.MyClass = (function(){
var _privateStaticVar = "I am a static private variable";
var _privateFunction = function() {
return "I am a private function";
};
var Constructor = function(options) {
this.instanceVar = "I am an public instance variable";
this.setPrivateStaticVar = function(x) {
_privateStaticVar = x;
};
this.getPrivateStaticVar = function() {
return _privateStaticVar;
};
this.exposePrivateFunction = _privateFunction;
};
Constructor.prototype = {
constructor: afsi.MyClass,
name: "afsi.MyClass",
version: "1.0"
};
return Constructor;
}());
var v1 = new afsi.MyClass(options);
var v2 = new afsi.MyClass(options);
11. Module Pattern – factory (functional, revealing)
var afsi = afsi || {};
afsi.calculator = (function(){
var _add = function (n1, n2) {
return n1+n2;
};
var _substract = function (n1, n2) {
return n1-n2;
};
var _calculatorFactory = function () {
var _m = 0;
var _setM = function (m) {
_m = m;
};
var _getM = function () {
return _m;
};
return {
add: _add,
substract: _substract,
setM: _setM,
getM: _getM
};
};
return _calculatorFactory;
}());
var calc = afsi.calculator();
12. Dispatching (Publisher/Subscriber)
var afsi = afsi || {};
afsi.messenger = (function () {
var _messengerFactory = function() {
var _messages = [];
var _subscribeMessage = function (messageName, callBack) {
if (typeof messageName === "string" && typeof callBack === "function") {
if (typeof _messages[messageName] === "undefined") {
_messages[messageName] = [];
}
_messages[messageName].push(callBack);
}
};
var _sendMessage = function (messageName, message) {
if (typeof messageName === "string" && typeof _messages[messageName] !== "undefined") {
for (var _counter = 0, max = _messages[messageName].length; _counter < max; _counter++) {
_messages[messageName][_counter](message);
}
}
};
return {
subscribeMessage: _subscribeMessage,
sendMessage: _sendMessage
};
}
return _messengerFactory;
} ());
13. Putting it all together
//Controller
afsi.namespace("afsi.myPage.controller");
afsi.myPage.controller = (function () {
var _processSearchData (searchData) {
//process the search data
return searchData;
}
var _ctrFactory = function (model,view, messenger) {
messenger.subscribeMessage(
"myPage.search_onkeypress",
function (text) {
model.searchProducts(text);
}
);
messenger.subscribeMessage(
"myPage.search_result",
function (searchData) {
searchData = _processSearchData(searchData);
view.showSearchResult(searchData);
}
);
};
return _ctrFactory;
} ());
//View
afsi.namespace("afsi.myPage.view");
afsi.myPage.view = (function () {
var _showSearchResult = function(searchData){
//bind UI with searchData
…
}
var _viewFactory = function (messenger) {
$("#searchInput").on("keypress", {},
function (event) {
messenger.sendMessage(
"myPage.search_onkeypress",
this.value
);
}
);
return {
showSearchResult: _showSearchResult
};
}
return _viewFactory
} ());
14. //Model
afsi.namespace("afsi.myPage.model");
afsi.myPage.model = (function () {
var _modelFactory = function (messenger) {
var _searchProducts = function(text){
$.ajax({
url: "/api/Products/SearchProducts?q="+text,
type: 'GET',
cache: false,
success: function (result) {
messenger.sendMessage(
"myPage.search_result",
Result
);
},
error: function (result) {
alert("Some error message")
}
});
}
return {
searchProducts: _searchProducts
};
}
return _modelFactory;
} ());
//Page initialization
$(function () {
var messenger = afsi.messenger();
afsi.myPage.controller(
afsi.myPage.model(messenger),
afsi.myPage.view(messenger),
messenger
);
});
15. Unit Testing (QUnit)
(function() {
module('Dispatcher Test');
test( "Subscriber should be called and receceive the message", function() {
//expected assertion #
expect(3);
//reate instance
var m = afsi.messenger();
//set up
m.subscribeMessage("afsi.test", function(message) {
//assertions
ok( true, "function called" );
ok( typeof message !== 'undefined', "message is defined" );
ok( message.data === 'something', "data has the correct value" );
});
//stimulus
m.sendMessage("afsi.test", { data: 'something' })
});
…
}());
17. References
Eloquent JavaScript
http://eloquentjavascript.net/index.html
Learning Advanced Javascript
http://ejohn.org/apps/learn/
Google Talks: How JavaScript Works
http://www.youtube.com/watch?v=ljNi8nS5TtQ
Prototypes and Inheritance in JavaScript
http://msdn.microsoft.com/en-us/magazine/ff852808.aspx
Functional inheritance vs. prototypal inheritance
http://www.richard-foy.fr/blog/2011/10/30/functional-inheritance-vs-prototypal-inheritance/
Namespacing in JavaScript
http://javascriptweblog.wordpress.com/2010/12/07/namespacing-in-javascript/
JavaScript Module Pattern: In-Depth
http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html
ECMAScript 5 Strict Mode, JSON, and More
http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/#!
QUnit: Introduction to Unit Testing
http://qunitjs.com/intro/
alert("Thank You!");