『javascript設計モード』ノートの第六章:方法のチェーン呼び出し
17121 ワード
この章で実現するのはjQueryのチェーン呼び出しです.例:
一:呼び出しチェーンの構造
:
まず、最も簡単な$()関数の実装を見てみましょう.
もし私たちが$()を実現するならば.method()という使い方は,$()関数に戻り値があり,オブジェクトを返すべきであると考えられる.前述したように、最善の方法は$()の中にnewオブジェクトを出すクラスがあるはずなので、上のコードは次のようになります.
また、オブジェクトを呼び出す方法があるはずです.prototypeに定義しましょう.コードは次のようになります.
ここまで来たら、大まかに使えます.
二:メソッドチェーン呼び出しをサポートするJavaScriptライブラリを設計する
:
一般的なjsライブラリには、イベント、DOM、Ajaxという重要なモジュールが含まれています.では、真似してみましょう.
実用的なのはやはり上の方法です.
しかし、一番上の何行かのコードに気づきましたか.第1章で言ったように、prototypeを追加する方法もチェーン呼び出しで遊び始めたのを覚えています.
また、最後から4行目はwindow.$に関数を与えています.これにより、$をネーミングスペースとして使用するライブラリと競合します.例えば、jQueryと競合しています.ネーミングスペースを変更しましょう.次に、ネーミングスペースを変更するためのインストーラを実現します.
上記のコードの主な考え方は、グローバル変数に値を割り当てず、installHelperを呼び出して対応するネーミングスペースをバインドしてから使用することです.
使用方法は次のとおりです.
これはwindow.$に関数を割り当てることに等しい.しました.
3:コールバックを使用してチェーン呼び出しをサポートする方法からデータを取得する
:
上記のチェーンメソッドはthisを返しますが、メソッド自体が値を返しますか?では、thisに戻ると衝突するのではないでしょうか.だからこの場合、私たちはこのような状況に対して、コールバック関数を入力して、戻ってきた数値を呼び出し、その後もthisを返す方法を考えなければなりません.
例:
上のコードはgetNameのどこを見てもいいので、コールバック関数を入力し、値を取り出して直接呼び出し、その後thisを返してチェーン呼び出しを破壊しません.
上のコードの1つの使用方法:
$(this).setStyle('color', 'green').show();
一:呼び出しチェーンの構造
:
まず、最も簡単な$()関数の実装を見てみましょう.
function $() {
var elements = [];
for (var i = 0, len = arguments.length; i < len; ++i) {
var element = arguments[i];
if (typeof element == 'string') {
element = document.getElementById(element);
}
if (arguments.length == 1) {
return element;
}
elements.push(element);
}
return elements;
}
もし私たちが$()を実現するならば.method()という使い方は,$()関数に戻り値があり,オブジェクトを返すべきであると考えられる.前述したように、最善の方法は$()の中にnewオブジェクトを出すクラスがあるはずなので、上のコードは次のようになります.
(function() {
// Use a private class.
function _$(els) {
this.elements = [];
for (var i = 0, len = els.length; i < len; ++i) {
var element = els[i];
if (typeof element == 'string') {
element = document.getElementById(element);
}
this.elements.push(element);
}
}
// The public interface remains the same.
window.$ = function() {
return new _$(arguments);
};
})();
また、オブジェクトを呼び出す方法があるはずです.prototypeに定義しましょう.コードは次のようになります.
(function() {
function _$(els) {
// ...
}
_$.prototype = {
each: function(fn) {
for ( var i = 0, len = this.elements.length; i < len; ++i ) {
fn.call(this, this.elements[i]);
}
return this;
},
setStyle: function(prop, val) {
this.each(function(el) {
el.style[prop] = val;
});
return this;
},
show: function() {
var that = this;
this.each(function(el) {
that.setStyle('display', 'block');
});
return this;
},
addEvent: function(type, fn) {
var add = function(el) {
if (window.addEventListener) {
el.addEventListener(type, fn, false);
}
else if (window.attachEvent) {
el.attachEvent('on'+type, fn);
}
};
this.each(function(el) {
add(el);
});
return this;
}
};
window.$ = function() {
return new _$(arguments);
};
})();
ここまで来たら、大まかに使えます.
$('test-1', 'test-2').show().
setStyle('color', 'red').
addEvent('click', function(e) {
$(this).setStyle('color', 'green');
});
二:メソッドチェーン呼び出しをサポートするJavaScriptライブラリを設計する
:
一般的なjsライブラリには、イベント、DOM、Ajaxという重要なモジュールが含まれています.では、真似してみましょう.
Function.prototype.method = function(name, fn) {
this.prototype[name] = fn;
return this;
};
(function() {
function _$(els) {
// ...
}
/* Events * addEvent * getEvent */
_$.method('addEvent', function(type, fn) {
// ...
}).method('getEvent', function(e) {
// ...
}).
/* DOM * addClass * removeClass * replaceClass * hasClass * getStyle * setStyle */
method('addClass', function(className) {
// ...
}).method('removeClass', function(className) {
// ...
}).method('replaceClass', function(oldClass, newClass) {
// ...
}).method('hasClass', function(className) {
// ...
}).method('getStyle', function(prop) {
// ...
}).method('setStyle', function(prop, val) {
// ...
}).
/* AJAX * load. Fetches an HTML fragment from a URL and inserts it into an element. */
method('load', function(uri, method) {
// ...
});
window.$ = function() {
return new _$(arguments);
});
})();
実用的なのはやはり上の方法です.
しかし、一番上の何行かのコードに気づきましたか.第1章で言ったように、prototypeを追加する方法もチェーン呼び出しで遊び始めたのを覚えています.
また、最後から4行目はwindow.$に関数を与えています.これにより、$をネーミングスペースとして使用するライブラリと競合します.例えば、jQueryと競合しています.ネーミングスペースを変更しましょう.次に、ネーミングスペースを変更するためのインストーラを実現します.
Function.prototype.method = function(name, fn) {
// ...
};
(function() {
function _$(els) {
// ...
}
_$.method('addEvent', function(type, fn) {
// ...
})
// ...
window.installHelper = function(scope, interface) {
scope[interface] = function() {
return new _$(arguments);
}
};
})();
上記のコードの主な考え方は、グローバル変数に値を割り当てず、installHelperを呼び出して対応するネーミングスペースをバインドしてから使用することです.
使用方法は次のとおりです.
installHelper(window, '$');
$('example').show();
これはwindow.$に関数を割り当てることに等しい.しました.
3:コールバックを使用してチェーン呼び出しをサポートする方法からデータを取得する
:
上記のチェーンメソッドはthisを返しますが、メソッド自体が値を返しますか?では、thisに戻ると衝突するのではないでしょうか.だからこの場合、私たちはこのような状況に対して、コールバック関数を入力して、戻ってきた数値を呼び出し、その後もthisを返す方法を考えなければなりません.
例:
window.API2 = window.API2 || {};
API2.prototype = function() {
var name = 'Hello world';
// Privileged mutator method.
setName: function(newName) {
name = newName;
return this;
},
// Privileged accessor method.
getName: function(callback) {
callback.call(this, name);
return this;
}
}();
上のコードはgetNameのどこを見てもいいので、コールバック関数を入力し、値を取り出して直接呼び出し、その後thisを返してチェーン呼び出しを破壊しません.
上のコードの1つの使用方法:
var o2 = new API2;
o2.getName(console.log).setName('Meow').getName(console.log);