[英]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.