2

简化示例代码:

var $ = function(selector, node) { // Selector engine
    var selector = selector.trim(), node = node || document.body;
    if (selector != null) {
        return Array.prototype.slice.call(node.querySelectorAll(selector), 0); }
    }
}

我想像这样使用它......:

$("div").innerHTML='It works!';

...不是这样的...:

$("div")[0].innerHTML='It works only on the specified index!';

...或这个:

for(i=0;i<$('div');i++) {
        $("div")[i].innerHTML='It works great but it's ugly!';
}

这是我得到的最接近的。我希望链接工作并使其与本机方法兼容:

if(!Array.prototype.innerHTML) { 
    Array.prototype.innerHTML = function(html) {
        for (var i = 0; i < this.length; i++) {
            this[i].innerHTML = html;
        }
    }
}

$("div").innerHTML('It works, but it ruins method chaining!');

我决定构建这个引擎来更好地学习 JavaScript;它正在工作,但我希望我能从 Stack Overflow 的好心成员那里学到更多东西。任何帮助将非常感激!

4

2 回答 2

4

我想像这样使用它......:

$("div").innerHTML='It works!';

...不是这样的...:

$("div")[0].innerHTML='It works only on the specified index!';

听起来您希望将一innerHTML组结果分配给所有结果。innerHTML

为此,您必须直接或间接使用一个函数。

直接地:

var $ = function(selector, node) { // Selector engine
    var selector = selector.trim(),
        node = node || document.body,
        rv;
    if (selector != null) {
        rv = Array.prototype.slice.call(node.querySelectorAll(selector), 0); }
        rv.setInnerHTML = setInnerHTML;
    }
    return rv;
}
function setInnerHTML(html) {
    var index;

    for (index = 0; index < this.length; ++index) {
        this[index].innerHTML = html;
    }
}

// Usage
$("div").setInnerHTML("The new HTML");

在那里,我们定义了一个函数,并将它分配给您作为属性返回的数组。然后,您可以在数组上调用该函数。Object.defineProperty(如果它可用于设置属性,您可能想要使用它setInnerHTML,因此您可以使其不可枚举。)

间接(需要启用 ES5 的 JavaScript 引擎):

var $ = function(selector, node) { // Selector engine
    var selector = selector.trim(),
        node = node || document.body,
        rv;
    if (selector != null) {
        rv = Array.prototype.slice.call(node.querySelectorAll(selector), 0); }
        Object.defineProperty(rv, "innerHTML", {
            set: setInnerHTML
        });
    }
    return rv;
}
function setInnerHTML(html) {
    var index;

    for (index = 0; index < this.length; ++index) {
        this[index].innerHTML = html;
    }
}

// Usage
$("div").innerHTML = "The new HTML";

在那里,我们使用Object.defineProperty为属性定义一个 setter。

在下面的评论中你说

我有一些原型在单独附加到 $ 函数时可以工作。示例:$('div').makeClass('this');当它们被链接在一起时,它们不起作用。例子:$('div').makeClass('this').takeClass('that');

要使链接工作,您可以return this;从每个函数中执行(所以 endmakeClass会执行return this;)。那是因为当您链接时,例如obj.foo().bar(),您正在调用bar的返回值foo。所以为了使链接工作,你确保foo返回thisfoo被调用的对象)。

于 2012-12-09T07:47:53.547 回答
0

这是有效的;它与我在前面的示例中给出的语法略有不同,但最终结果是相同的。我从其他 Stack Exchange 成员那里得到了很大的帮助,再次感谢大家。

var $ = function(selector, node) { // Selector engine
    var selector = selector.trim(), node = node || document.body;
    if (selector != null) {
        return Array.prototype.slice.call(node.querySelectorAll(selector), 0); }
    }
}

if(!Array.prototype.html) { 
    Array.prototype.html = function(html) {
        for (var i = 0; i < this.length; i++) {
            this[i].innerHTML = html;
        }
        return this; //<---- Silly me, my original code was missing this.
    }
}

当我运行它时,一切(包括链接)都按需要工作:

$("div").html('hello world');

输出:

<div>hello world</div>

干杯!

于 2012-12-10T02:11:24.000 回答