代码之家  ›  专栏  ›  技术社区  ›  Shannon Hochkins

从属性字符串运行函数

  •  4
  • Shannon Hochkins  · 技术社区  · 12 年前

    我有一个这样的选择菜单:

    HTML格式

    <select name="moduleGroup">
        <option data-function="getListing('pages')">Pages</option>
    </select>
    

    Java脚本

    function getListing(s) {
        console.log(s);
    }
    
    $('select').on('change', function() {
        var func = $(this).find('option:selected').attr('data-function');
        [func]();
    });
    

    我也尝试过, $[func](); , $('body')[func]();

    我读过多篇关于同一问题的帖子,但没有一篇对我有帮助: here 和 here

    我肯定我做错了什么,但有人能告诉我正确的方向吗?

    1 回复  |  直到 9 年前
        1
  •  2
  •   Katie Kilian Fenton    12 年前

    最简单的方法是打电话 eval() 这样地:

    $('select').change(function() {
        var func = $(this).find('option:selected').attr('data-function');
        eval(func);
    });
    

    小提琴: http://jsfiddle.net/gywzb/4/

    但全世界都认为这是一种糟糕的做法。 正如我最喜欢的linter所说,“eval()是邪恶的。”它会给你带来很多令人讨厌的安全漏洞(尤其是当你维护应用程序时,事情会从最初的编写方式发生变化),而且性能也非常糟糕。幸运的是,还有更好的方法。

    首先,我将稍微分解一下数据属性,这样,您就可以拥有两个属性,一个用于函数名,另一个用于参数,而不是一个包含函数名和参数的属性。

    <select name="moduleGroup">
        <option data-function="getListing" data-parameter="pages">Pages</option>
    </select>
    

    其次,我们将创建一个包装函数的“类”,如下所示:

    var MyClass = function() {
    }
    
    MyClass.prototype = {
        getListing: function(s) {
            console.log(s);
        }
    };
    

    最后,下面是如何使用上述更改来调用函数:

    $('select').on('change', function() {
        var func = $(this).find('option:selected').attr('data-function');
        var param = $(this).find('option:selected').attr('data-parameter');
    
        var myInstance = new MyClass();
        var funcRef = myInstance[func];
        funcRef.call(myInstance, param);
    });
    

    以下是整件事: http://jsfiddle.net/7CwH4/2/

    当你使用 .call method 调用函数。这个 .call() 方法的第一个参数是函数将看到的对象 this 对象下一个参数 .call 是函数的第一个参数。(如果你的函数需要更多的参数 呼叫 将是函数的第二个参数等。请参见 MDN documentation 对于 呼叫 如果这令人困惑。)

    如果需要传递比字符串更复杂的数据作为参数,可以将其放入 data-parameter 属性作为JSON字符串,然后使用 $.parseJSON 在将参数传递给函数之前将其转换为对象:

    // If your data-parameter attribute contained a JSON string.
    $('select').on('change', function() {
        var func = $(this).find('option:selected').attr('data-function');
        var param = $(this).find('option:selected').attr('data-parameter');
    
        var paramObj = $.parseJSON(param);
    
        var myInstance = new MyClass();
        var funcRef = myInstance[func];
        funcRef.call(myInstance, paramObj);
    });