モジュール設計
CommonJS規範
node.js 主にServer側 synchronous
var math = require('math');
math.add(2,3);
AMD規範
require.js 主にBrowser側 asynchronous
require(['math'], function(math){
math.add(2, 3);
});
基本モジュール
var jsModule = function(){
var privateVar = "A";
var privateMethod = function(){
return privateVar;
};
return {
printVar: function(){
return privateMethod();
}
};
}();
console.log(jsModule.printVar()); //A
子モジュール
jsModule.subModule = function(){
var anotherPrivateVar = "B";
var sayWord = function(str){
switch(str)
{
case "A":
return "A B";
default:
return "C";
}
};
return {
say: function(){
return sayWord(jsModule.printVar());
}
}
}();
console.log(jsModule.subModule.say()); //A B
メソッドを追加
var jsModule = function(){
var privateVar = "A";
var privateMethod = function(){
return privateVar;
};
var obj = {
printVar: function(){
return privateMethod();
}
};
obj.appendVar = function(){ //追加
return "B";
}
return obj;
}();
console.log(jsModule.printVar()); //A
console.log(jsModule.appendVar()); //B
拡張モジュール
var newJsModule = function(super_module){
var parent_module = super_module;
parent_module.printVar = function(){ //Override
return "B";
};
var privateMethod2 = function(){
return "D";
};
return {
newPrintVar: function(){
return parent_module.printVar();
}
}
}(jsModule);
console.log(newJsModule.newPrintVar()); //B
関数型プログラミング
★高階関数
・引数として関数を受け取る
書き方1
(function(f, a) {
return f(a) + f(a);
})(function(n) {
return n * n;
}, 10); // 200
書き方2
var g = function(f, a) { return f(a) + f(a); };
var h = function(n) { return n * n; };
g(h, 10); // 200
・戻り値として関数を返す
書き方1
var g = function(n) {
return function() {
return n * n;
};
};
呼び方1
var h = g(10);
h(); // 100
呼び方2
g(10)(); // 100
書き方2
(function(n) {
return function() {
return n * n;
};
})(10)(); // 100
★モジュール構造
(function(MyModule, $, undefined) {
MyModule.help = {
...
};
MyModule.help.cache = {
...
};
...
}(window.MyModule || {}, jQuery));
オブジェクト向けの設計
1.コンストラクタ+プロトタイプ方式
特徴:thisとprototypeを使う
・クラスの書き方
・書き方1
function Parent(sColor) {
this.color = sColor;
}
prototypeを再定義
Parent.prototype = {
showColor: function(){
alert(this.color);
}
};
prototypeにプロパティを追加
Parent.prototype.showColor = function() {
alert(this.color);
}
・書き方2
function Parent(sColor) {
this.color = sColor;
if (typeof showColor != "function" ){ // if(this.showColor === undefined)
Parent.prototype.showColor = function() {
alert(this.color);
};
}
}
//利用側
var class1 = new Parent("red");
class1.showColor();
class1.showColor = function () { //処理変更
// do something
}
・書き方3
var Parent = function(){
this.color = "green";
this.prototype.showColor = function() {
alert(this.color);
};
};
・継承の書き方
・書き方1
function Child(sColor, sName) {
Parent.apply(this, arguments);
this.name = sName;
}
・書き方2
Child.prototype = new Parent(); ←メモリ消費
Child.prototype.constructor = Child;
Child.prototype.showName = function() {
alert(this.name);
}
//利用側
・呼び方1
var class1 = new Child("red", "Andy");
class1.showName();
・呼び方2
var class2 = {};
Child.call(class2, "red", "Andy"); //書き方1
Child.apply(class2, ["red", "Andy"]); //書き方2
class2.showName();
・書き方3(推薦)
function extend(Sub, Super) {
var F = function(){};
F.prototype = Super.prototype;
Sub.prototype = new F();
Sub.prototype.constructor = Sub;
Sub.uber = Super.prototype;
}
//利用側
extend(Child, Parent);
var class1 = new Child("red", "Andy");
class1.showName();
※callとapplyの違いは2番目からの引数
2.Minimalist方式
特徴:thisとprototypeを使わない
・クラスの書き方
・書き方1
var Parent = {
createNew: function(){
var parent = {};
parent.color = "xxx";
parent.showColor = function(){...};
return parent;
}
};
・書き方2
var Parent = {
createNew: function(){
var parent = {
color : "xxx",
showColor : function() {
...
}
};
return parent;
}
};
//利用側
var class1 = Parent.createNew();
class1.showColor();
・継承の書き方
var Child = {
createNew: function(){
var val = "xxx"; //private変数
var method = function() { ... }; //privateメソッド
var child = Parent.createNew();
child.name = "yyy"; //publicプロパティ
child.action = function(){...}; //publicメソッド
return child;
}
};
・getter/setterの書き方
var Sample = {
name : "xxx",
createNew: function(){
var sample = {};
sample.getName = function(){ return Sample.name; };
sample.setName = function(x){ Sample.name = x; };
return sample;
}
};
//利用側
var sample1 = Sample.createNew ();
var sample2 = Sample.createNew ();
sample1.getName(); //出力:xxx
sample2.setName("yyy");
sample1.getName(); //出力:yyy