メソッドを外にだして使う
- -> 文字列のメソッド名を引数としてプラグインのメソッドを呼び出す
- -> EObject.definePropertyによるカプセル化
- -> Object.defineProperty( オブジェクト , プロパティ名 , プロパティ記述子 )
- -> $.proxy thisを固定?
//文字列のメソッド名を引数としてプラグインのメソッドを呼び出す
(function($) {
var methods = {
init : function( options ) { // THIS },
init : function( optiois ) {
// 'resize.tooltip' で 名前空間を指定して reposition メソッドを実行するようバインド設定
return this.each( function() {
$(window).bind('resize.tooltip', methods.reposition );
});
},
destroy : function() {
// '.tooltip' の名前空間指定でイベントをアンバインド
return this.each( function() {
$(window).unbind('.tooltip');
});
},
show : function() { // IS },
hide : function() { // GOOD },
update : function( content ) { // !!! }
};
$.fn.tooltip = function( method ) {
// Method calling logic
if ( methods[method] ) {
// メソッドが存在するなら、メソッドの呼出を行う。
return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1));
} else if (typeof method === 'object' || !method ) {
// メソッドの指定がなければ、init()を呼び出す。
return methods.init.apply( this, arguments );
} else {
// 存在しないメソッドが呼び出された場合などはエラーとする。
$.error( 'Method '+method+' dose not exist on jQuery.tooltip' );
}
};
})(jQuery);
$('div').tooltip(); // calls the init method
$('div').tooltip({
foo:'bar'
}); // calls the init method
$('div').tooltip('hide'); // calls the hide method
$('div').tooltip('update', 'This is the new tooltip content!');
//Object.defineProperty()を使う
;(function($) {
Object.defineProperty($.fn, 'myPlugin', {
enumerable: false,
get: function () {
//thisキーワードをバインドした初期化関数を作成
var initialize = $.proxy(init, this);
//メソッド群はこの関数のプロパティに代入する
initialize.method1 = method1;
initialize.method2 = method2;
return initialize;
}
});
//初期化関数を定義する
function init() {
//忘れずにthisキーワードを返す
return this;
}
function method1() {
....
return this;
}
function method2() {
....
return this;
}
})(jQuery);
//プラグインを実行(初期化)してからメソッドを呼び出す。
$('#my-plugin').myPlugin();
$('#my-plugin').myPlugin.method1();
;(function($) {
//追加・変更点をハイライト
Object.defineProperty($.fn, 'myPlugin', {
enumerable: false,
get: function () {
var initialize;
//初期化関数がキャッシュされていなければ新規に作成
if (!this.data('initialize')) {
initialize = $.proxy(init, this);
initialize.method1 = method1;
initialize.method2 = method2;
this.data('initialize', initialize);
} else {
//すでにキャッシュ済みならそちらを使用する
initialize = this.data('initialize');
}
return initialize;
}
});
function init() {
if (!this.data('initialized')) {
this.data('initialized', true);
//初期化処理
....
}
return this;
}
//初期化したかどうかで条件分岐させる
function method1() {
if (!this.data('initialized')) {
init.apply(this);
}
....
return this;
}
function method2() {
if (!this.data('initialized')) {
init.apply(this);
}
....
return this;
}
})(jQuery);
//初期化を自動化
$('#my-plugin').myPlugin.method1();
return thisでメソッドチェーン
var base = function(){
console.log("base");
return this;
};
var chain = function(){
console.log("chain");
return this;
};
//base chain chain chain
base().chain().chain().chain();
newとprototypeを使って実現
参考:参考リンク
//newとprototypeを使って実現
var builder = function( str ) {
// インスタンスをbuilderの中で生成
return new builder.prototype.init( str );
};
builder.prototype = {
// 初期化メソッド( initという名前じゃなくてもいいです )
init: function( str ) {
// コンストラクタ的なのをbuilder.prototype.initの中に書く
if ( typeof str === 'undefined' ) {
this._str = '';
} else {
this._str = '' + str; // 型変換
}
},
// 文字連結
append: function( str ) {
this._str += '' + str;
// 自分自身を返す
return this;
},
// 連結した文字列を返す
get: function() {
return this._str;
}
}
// builder.initのprototypeにbuilderのprototypeを持たせる
builder.prototype.init.prototype = builder.prototype;
//実行
var result = builder().append( 'hoge' ).append( 'fuga' ).append( 'moge' ).get();
console.log( result );
// > hogefugamoge
簡易電卓
instanceof 演算子は、オブジェクトが自身のプロトタイプにコンストラクタの prototype プロパティを持っているかを確認します。戻り値はブール値です。
!function( window ) {
// 簡易電卓クラス
// 3 * ( 1 + 3 ) / 6
// みたいな式を
// calc( 3 ).multiply( calc( 1 ).plus( 3 ) ).divide( 6 ).get();
// こんな感じで使えるように
var calc = function( num ) {
// calcクラスであればそのまま返す
if ( num instanceof calc ) {
return num;
}
// 数字以外は0にする
if ( typeof num !== 'number' ) {
num = 0;
}
// インスタンス生成
return new calc.prototype.init( num );
}
calc.prototype = {
// コンストラクタ
init: function( num ) {
this._num = num;
},
// たす
plus: function( num ) {
this._num += calc( num ).get();
return this;
},
// ひく
minus: function( num ) {
this._num -= calc( num ).get();
return this;
},
// かける
multiply: function( num ) {
this._num *= calc( num ).get();
return this;
},
// わる( 0でわることを考慮してない )
divide: function( num ) {
this._num /= calc( num ).get();
return this;
},
// 取得
get: function() {
return this._num;
}
}
// initのprototypeにcalcのprototypeをつっこむ
calc.prototype.init.prototype = calc.prototype;
window.calc = calc;
}( window );
// 10 + 20
calc( 10 ).plus( 20 ).get();
// > 30
// ( 9 - 7 ) * 5
calc( 9 ).minus( 7 ).multiply( 5 ).get();
// > 10
// 3 * ( 1 + 3 ) / 6
// 括弧内の計算はcalcでおこないそのオブジェクト自体を引数に指定する
calc( 3 ).multiply( calc( 1 ).plus( 3 ) ).divide( 6 ).get();
// > 2
クロージャーでメソッドチェーン(推奨)
var simplecalc = (function() {
var value = 0;
return {
add : function(num) {
value += num; // 足し算
return this; // thisを返す
},
sub : function(num) {
value -= num; // 引き算
return this; // thisを返す
},
val : function(){
return value; // 結果表示。valueを返す
}
};
})();
console.log(simplecalc.add(10).sub(5).val()); // 5
newとprototypeでメソッドチェーン
//Oreily p125
var SimpleCalc = function(){
this.value = 0;
}
SimpleCalc.prototype = {
add : function(num){
this.value += num; // 足し算
return this; // thisを返す
},
sub : function(num){
this.value -= num; // 引き算
return this; // thisを返す
},
val : function(){
return this.value; // 結果表示。this.valueを返す
}
};
var instance = new SimpleCalc();
console.log( instance.add(10).sub(5).val() ); // 5