Javascript 理解链式函数,如何像元素本身一样返回jquery,如何避免“…不是函数”

Javascript 理解链式函数,如何像元素本身一样返回jquery,如何避免“…不是函数”,javascript,jquery,chained,Javascript,Jquery,Chained,完全是实验性的,只是为了学习,我试图重新发明轮子,一个叫做jquery的轮子。这样做的最初目的是理解可链接函数。 所以我写了一个函数,它可以做到这一点,就我所见,非常好,就像这样:有点缩短 var $ = function(s) { var el = document.querySelectorAll(s); var myobj = { addClass(className) { el.forEach(elem => {elem.c

完全是实验性的,只是为了学习,我试图重新发明轮子,一个叫做jquery的轮子。这样做的最初目的是理解可链接函数。 所以我写了一个函数,它可以做到这一点,就我所见,非常好,就像这样:有点缩短

var $ = function(s) {
    var el = document.querySelectorAll(s);

    var myobj = {
        addClass(className) {
            el.forEach(elem => {elem.classList.add(className)});
            return this;
        },
        toggleClass(className) {
            el.forEach(elem => {elem.classList.toggle(className)});
            return this;
        },
        removeClass(className) {
            el.forEach(elem => {elem.classList.remove(className)});
            return this;
        },
        html(html) {
            if (typeof html == 'string') {
                el.forEach(elem => {elem.innerHTML = html});
                return this;
            } else {
                return el[0].innerHTML;
            }
        }
    };

    return myobj;
};
这确实是一个工作示例,现在我可以使用类似jquery的语法来操作类和元素的html或元素的节点列表,如:$'test'.html'new html content';或者像$'a'.html'my new link'.addClass'newclassname';一样链接;,这真的很酷

对于感兴趣的人,这里是完整的示例,包括css和attr,以及缺少的jquery函数id

我的问题是:

[已解决]如何让此函数返回jquery,就像var elm=$'divtest'这样的元素本身一样;,现在我要取回整个物体

[决议]plz。请参阅下面的注释,如果我使用的是当前未包含在该函数中的方法,例如$'divtest'.addClass'newclass'.animate{top:'2.3em',background:'red'},则如何编写回退函数以防止获得错误消息,如$...animate不是一个函数;,因为动画目前还没有实现。在php中有一个uuuu get函数,javascript中有类似的功能吗

请不要问我为什么要这么做,因为我提到这是为了学习和理解

谢谢

如何让这个函数返回jquery,就像元素本身一样,比如var elm=$'divtest';,现在我要取回整个物体

jQuery总是返回整个jQuery对象。如果您指的是您定义的addClass…方法如何不与对象一起出现在浏览器控制台中,这是通过与共享这些属性而不是为每个对象创建一组新函数来实现的。ES6类是创建构造函数的一种方便方法,它允许您使用方法定义原型并创建从原型继承的对象:

class MyElementCollection {
    constructor(el) {
        this.el = el;
    }

    addClass(className) {
        this.el.forEach(elem => {elem.classList.add(className)});
        return this;
    }

    // ⋮
}

var $ = function(s) {
    var el = document.querySelectorAll(s);

    return new MyElementCollection(el);
};
然后,如果您希望它像Firefox上的数组一样显示,并且像jQuery一样,索引$'divtest'[0]可以访问元素,则可以将元素分配给这些索引,并为集合指定长度:

如果我正在使用当前未包含在该函数中的方法,例如$'divtest'.addClass'newclass'.animate{top:'2.3em',background:'red'},我如何编写回退函数来防止获得错误消息,如$..animate不是一个函数;,因为动画目前还没有实现。在php中有一个uuuu get函数,javascript中有类似的功能吗

您可以用JavaScript实现这一点,但我不推荐使用它——它不是很干净。您的对象将假装拥有所有属性,而不仅仅是jQuery中尚未实现的属性,并且在原型上不会有它们的列表。代理还附带性能和可理解性惩罚。相反,考虑将所有未实现的内容分配为相同的实现:

class MyElementCollection {
    // ⋮
}

const notImplemented = () => {
    throw new Error('Not implemented');
};

['animate', …].forEach(name => {
    MyElementCollection.prototype[name] = notImplemented;
});

看看jquery的github repo。相关文件如下:

jQuery以一种比我在这里要更复杂的方式来处理它,所以这只是一个基本的解释

jQuery函数及其$alias调用新的jQuery.fn.initselector,根在它们的函数体中。这将创建一个新的jQuery集合,这是他们在jQuery.prototype文档中使用的术语。该原型附带了所有常用的jQuery方法,如on、find、animate等

他们这样做:

function jQuery (selector, root) {
  return new jQuery.fn.init(selector, root);
}

jQuery.fn = jQuery.prototype = { /* skipped */ }

jQuery.fn.init = function (selector, root) { /* skipped */ }
jQuery.fn.init.prototype = jQuery.fn;
这里的关键是最后一行,他们将jQuery.prototype也作为jQuery.fn.init的原型。不要被fn弄糊涂了,这只是他们使用的另一个别名,所以他们不必一直键入prototype

扫描jQuery.fn.init构造函数时,您会注意到它们将所有匹配的DOM元素按索引存储到新集合中。简化:

jQuery.fn.init = function (selector, root) {
  let elms = Array.from(root.querySelectorAll(selector));
  elms.forEach((el, index) => {
    this[index] = el;
  }, this);
}
他们在幕后做了很多事情,但这基本上解释了jQuery集合是什么:一种自定义类型的对象,部分看起来像节点列表,但有一个自定义原型,它附带了所有jQuery方法

这意味着,您的第一个问题基于错误的假设:使用$'divtest'将返回包含单个元素的jQuery集合。您永远无法从jQuery获得原始DOM节点


至于你的第二个问题:你可以使用代理

不确定您的第一个问题是什么意思–当您使用jQuery时,$'divtest'将返回一个jQuery集合,而不是一个DOM元素。jQuery集合在概念上与myobj几乎相同,尽管它的构建方式不同。@David它不是jQuery。OP试图编写自己的代码来模仿jQuery的行为,以此作为一种学习努力。@TylerRoper是的,我知道。但我还是
不要通过说…来理解他的意思。。。元素本身……使用jQuery也不会得到“仅仅是元素本身”——它是一个jQuery对象,请尝试jQuery的$'divtest'实例。也许你指的是它在控制台中的外观,就像一个元素数组?@freedomn-m我从来都不知道\uuu noSuchMethod。我想建议。编辑:似乎“noSuchMethod”是非标准的,也被标记为过时。因此,代理可能是更好的选择。对于第一个问题,它在您回答之前解决得稍早一些。但是+1,因为答案正确,对我来说可以理解,好吧,回到第二个问题:我已经得到了代理的东西来工作。如果函数存在,我可以让它通过,或者获取自定义消息。但我仍然在控制台上收到浏览器错误消息,并破坏了其余代码。下面是实际的测试脚本,第二个问题也解决了:这不是很难,只是有时候新的东西需要一点理解。代理的事情终于帮了我的忙。真正的神奇发生在处理程序的else部分:如果传递的属性不是函数,那么从现在开始让它成为函数,它只创建自定义消息,但抑制javascript错误和代码中断。我现在对此感到非常高兴。再次感谢你们这些把我带到代理或反向的人。这是最后一句对不起,我来晚了,但谢谢你耐心地教我+1对于该类模型。
function jQuery (selector, root) {
  return new jQuery.fn.init(selector, root);
}

jQuery.fn = jQuery.prototype = { /* skipped */ }

jQuery.fn.init = function (selector, root) { /* skipped */ }
jQuery.fn.init.prototype = jQuery.fn;
jQuery.fn.init = function (selector, root) {
  let elms = Array.from(root.querySelectorAll(selector));
  elms.forEach((el, index) => {
    this[index] = el;
  }, this);
}