[英]Javascript: object return itself a.k.a. chaining
我正在嘗試構建自己的小jquery類庫,但是我正在創建這個鏈接模式的時間非常艱難。 基本上我有一個類有一堆方法,可以更容易地操作文檔。 這是一個例子
function MF(selector){
var DO; // Stands for DocumentObject
this.select = function(selector){
return document.getElementById(selector);
}
if(typeof selector === 'string'){
DO = this.select(selector);
}else if(selector instanceof HTMLElement){
DO = selector;
}
this.children = function children(selector){
return DO.getElementsByClassName(selector);
}
return {
MF: ???
}
}(null);
我的反思可能有問題,但我想弄清楚的是,為了獲得文檔對象(html元素)的其他方法,我需要擴展HTMLElement原型或者將元素與我的類一起傳遞。 我選擇了第二種選擇。 我只是無法弄清楚我的班級要回歸什么,以便我可以繼續進行鏈接。 為了這個例子,我簡單的目標是能夠編寫以下代碼行:
MF('someDiv').children('someClass');
在絕望的嘗試中,我嘗試返回一個新的MF
實例,默認情況下不應該有實例,並導致自己進入無限循環。 我真的無法想象我應該回到那里。 任何幫助是極大的贊賞!
return this;
將允許訪問構造函數的方法。 如果該方法不需要返回另一個值,請在構造函數的最底部以及屬於它的每個方法的最底部執行此操作。
function MF(selector){
var doc = document;
this.select = function(selector){
return doc.getElementById(selector);
}
// there are problems with some of your code
this.someMethod = function(){
/* do stuff - If you want to access an Element then
var thisIsNowGlobal = this.select('someId');
thisIsNowGlobal.innerHTML = 'someText';
Note, the keyword this is global not var
If you wrote this.select('someId').innerHTML the property would not exist
When a property of an Object is assigned to a variable or argument
the this value changes to the global context.
*/
return this;
}
return this;
}
看起來你也試圖使用模塊模式,並沒有利用原型..
當你想鏈接某些東西時,你需要在可鏈接的方法中返回它自己( this
),或者返回你的Object的new
實例。 在下面的例子中,我通過使用新實例來實現鏈接(好像孩子們看起來需要成為一個列表,所以我做了一個數組 )。
var MF = (function () { // module pattern start
function MF(selector) {
if (!(this instanceof MF)) return new MF(selector); // always construct
this.node = null; // expose your DO
if (typeof selector === 'string') {
this.node = document.getElementById(selector);
} else if (selector instanceof HTMLElement) {
this.node = selector;
} else {
throw new TypeError('Illegal invocation');
}
}
MF.prototype = {}; // set up any inheritance
MF.prototype.select = function (selector) {
return new MF(document.getElementById(selector)); // returns new instance
};
MF.prototype.children = function (selector) {
var MFs = [],
nodes = this.node.getElementsByClassName(selector),
i;
for (i = 0; i < nodes.length; ++i) {
MFs[i] = new MF(nodes[i]);
}
return MFs; // array of items of new instances
};
return MF; // pass refence out
}()); // module pattern end
然后,例如,您可以鏈接...
MF(document.body).children('answer')[0].children('post-text')[0].node;
你可以很容易地做到這一點。 請記住,當你return this
它時,如果this
有定義的方法,那么你可以按順序調用它們。
var MyUtilThing = function(){};
MyUtilThing.prototype.doStuff = function doStuff (){ // give it a name, helps in debugging
// do your thing
console.log('doing stuff');
return this; // this is your instance of MyUtilThing
}
var thing = new MyUtilThing();
thing.doStuff().doStuff().doStuff(); // etc
必須明確創建實例的一種方法是在構造函數中執行此操作。
var MyUtilThing = function(selector){
var F = function(){};
F.prototype = MyUtilThing.prototype;
var toReturn = new F();
toReturn.initialize(selector);
return toReturn;
};
MyUtilThing.prototype.initialize = function initialize(selector){
this.selector = selector;
};
MyUtilThing.prototype.doStuff = function doStuff (){ // give it a name, helps in debugging
// do your thing
console.log('doing stuff to', this.selector);
return this; // this is your instance created in the constructor (the blank function with the same prototype as MyUtilThing)
}
var thing = MyUtilThing('div'); // no use of new here!
thing.doStuff().doStuff().doStuff(); // etc
但是,在那里進入一些稍微沉重的領土。 最好的辦法就是嘗試和了解究竟如何this
是JS使用,你會得到一個很長的路要走。
傳統上,jQuery啟用鏈接的方式是為每種類型的返回值創建一個包裝器對象。 例如,在您的情況下,為HTMLElement
創建自己的包裝器是HTMLElement
:
function HTMLElementWrapper(element) {
if (element instanceof HTMLElementWrapper) return element;
this.element = element;
}
現在您有了一個HTMLElementWrapper
您可以按如下方式重構您的MF
功能:
function MF(selector) {
return new HTMLElementWrapper(typeof selector === "string" ?
document.getElementById(selector) : selector);
}
MF
函數現在返回一個HTMLElementWrapper
對象,它有兩個方法select
和children
:
HTMLElementWrapper.prototype.select = function (selector) {
return new HTMLElementWrapper(this.element.getElementById(selector));
};
HTMLElementWrapper.prototype.children = function (selector) {
return new NodeListWrapper(this.element.getElementsByClassName(selector));
};
Ofcourse為children
功能工作,你需要創建一個NodeListWrapper
構造函數:
function NodeListWrapper(list) {
if (list instanceof NodeListWrapper) return list;
this.list = list;
}
現在您可以按如下方式鏈接方法:
MF("someDiv").select("something").children("someClass");
要在.children("someClass")
之后鏈接方法,您需要將這些方法添加到NodeListWrapper.prototype
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.