【问题标题】:Attaching chained methods to collections of elements in JavaScript将链式方法附加到 JavaScript 中的元素集合
【发布时间】:2009-03-02 20:27:47
【问题描述】:

这 - 至少目前 - 纯粹是实验,但我很好奇:有没有办法将方法(通过原型)附加到元素集合?我已经测试了以下代码:

<div>a</div>
<div>b</div>
<div>c</div>
<script>
NodeList.prototype._ = function(s)
 {
    for (x = 0; x < this.length; x++)
     {
        eval('this[x]' + '.' + s);
     }
    return this;
 }
document.getElementsByTagName('div')._("style.backgroundColor = 'red'")._('innerHTML += x');
</script>

目前,它在 Opera 中完美运行;正如预期的那样,对所有 div 元素调用 _ 方法,然后依次对传递给它的字符串 onto 进行 eval() 处理。请注意,_ 方法允许链接,这也得到了证明,调用 _ 将预测的 x 迭代器变量附加到每个元素的 innerHTML。

现在,有两个问题...

首先,有没有更好的方法来解决这个问题?我一直希望我能做到document.getElementsByTagName('div').style.backgroundColor = "red";,但可惜,它还没有实现。这就是我首先这样做的原因,也是我如此简洁地命名该方法的原因;我正在尝试尽可能地模仿它。

其次,假设这是一个理智的用法,我将如何让它在 Firefox 中工作?该浏览器相当于NodeListHTMLCollection,但尝试对后者进行原型设计根本不会成功。有什么建议吗?

【问题讨论】:

    标签: javascript collections methods element chaining


    【解决方案1】:

    我已经制定了我认为可以作为可行解决方案的方法;使用这种方法对元素集合进行链式修改有什么不好的地方吗?

    <script>
    _ = function()
     {
        for (x = 0; x < arguments[0].length; x++)
         {
            for (y = 0; y < arguments[1].length; y++)
             {
                eval('arguments[0][x]' + '.' + arguments[1][y]);
             }
         }
     }
    </script>
    

    用法:

    divs = document.getElementsByTagName('div');
    _(divs, ["style.color = 'red'", "innerHTML += x"]);
    

    【讨论】:

    • 是的,你不需要 eval 。此外,由于您实际上只有 2 个参数,为什么不命名它们并使用 arguments[]array?
    【解决方案2】:

    这是您需要的“更漂亮”版本(没有 eval、没有全局变量、正式参数、字符串中没有丑陋的代码),而不是在原型上设置它,因为这不适用于 IE。

    /**
     * Sets a property on each of the elements in the list
     * @param {NodeList} list
     * @param {string} prop The name of property to be set, 
     *        e.g., 'style.backgroundColor', 'value'.
     * @param {mixed} value what to set the value to
     */
    function setListProp( list, prop, value) {    
        for (var i = 0; i < list.length; i++) {
            setProp(list[i], prop, value);
        }
    }
    
    /**
     * Avoids the use of eval to set properties that may contain dots
     * Why avoid eval? eval is slow and could be dangerous if input comes from 
     * an unsanitized source
     * @param {object} el object that will have its property set
     * @param {string} propName ('value', 'style.backgroundColor')
     * Example: setProp(node, 'style.backgroundColor', "#ddd");
     */
    function setProp(el, propName, value) {
        var propList = propName.split('.');
        // Note we're not setting it to the last value in the property chain
        for (var i=0; i < propList.length - 1 ; i++) {
            el = el[propList[i]];
        }
        var lastProperty = propList[propList.length -1];
        el[lastProperty] = value;
    }
    

    测试用例 使用 Firefox 访问 google.com,在控制台中输入上述代码,然后输入以下内容:

    // Set tooltip on links
    setListProp( document.getElementsByTagName('a'), 'title', 'YEAH it worked');
    
    
    // Set bg to red on all links
    setListProp( document.getElementsByTagName('a'), 'style.backgroundColor', '#f00');
    

    更新 如果您希望能够按照您提到的那样执行 +=,我的解决方案将不起作用。我认为最优雅的解决方案是使用如下回调循环。

    /** 
     * This exists in many libs and in newer versions of JS on Array's prototype 
     * @param {Object[]} arr The array that we want to act on each element. 
     *                   Does not work for sparse arrays
     * @param {Function} callback The function to be called for each element, it will be passed
     *        the element as its first argument, the index as the secibd
     */
    function iterate(arr, callback) {
      for (var i=0,item; item=arr[i]; i++) {
        callback(item, i);
      }
    }
    

    那你就可以这样称呼了

    var as = document.getElementsByTagName('a'); 
    iterate( as, function(el, index) {
      el.style.backgroundColor = 'red';
      el.innerHTML += "Whatever";
    });
    

    【讨论】:

      猜你喜欢
      • 2013-01-10
      • 1970-01-01
      • 2011-06-12
      • 2021-06-29
      • 2019-07-30
      • 2013-12-13
      • 1970-01-01
      • 1970-01-01
      • 2015-03-26
      相关资源
      最近更新 更多