代码之家  ›  专栏  ›  技术社区  ›  Matthew Lock fge

函数.toString()在现实世界中有哪些用途?

  •  14
  • Matthew Lock fge  · 技术社区  · 15 年前

    我在javascript中注意到,如果定义一个函数,比如 myfunction() ,然后打电话 myfunction.toString() ,您将获得该函数源的文本。这有什么有趣的/真实的用途吗?

    15 回复  |  直到 6 年前
        1
  •  14
  •   Guffa    15 年前

    好吧,你可以用它很容易地重新定义一个函数:

    function x() { alert('asdf'); }
    eval(x.toString().replace('asdf','hello'));
    x();
    

    这将警告字符串“hello”而不是字符串“asdf”。

    这可能有用。另一方面,由于维护代码的困难,自我修改的代码常常被拒绝。

        2
  •  11
  •   jsdw    12 年前

    这是个老问题,但这是我的2美分。

    使用node.js,这对于在服务器端创建函数很有用,然后将这些函数嵌入到页面中并发送到客户机。

    例如,dot.js模板引擎首先将模板编译成一个函数,然后执行该函数生成HTML代码。

    如:

    var compiled = dot.compile("<h1>{{=it.header}}</h1>");
    var html_output = compiled({header: "hello world"});
    

    因此,如果我们想在客户机中使用模板,而不需要每个客户机首先编译模板,我们可以为他们提供一个包含以下内容的评估结果的页面:

    "var compiled = " + dot.compile("<h1>{{=it.header}}</h1>").toString();
    

    然后,它将提供一个“已编译”的客户端函数,用于编译从Ajax请求发送到HTML客户端的数据。

        3
  •  8
  •   Matthew Crumley    15 年前

    我使用它自动生成函数的命名参数版本。例如,如果您有一个函数

    function f(a, b, c) {
        return a * b + c;
    }
    

    可以从中提取参数名称 f.toString() 并使用它生成一个您可以这样调用的函数:

    namedParametersF({ a: 2, b: 3, c: 4}); // f(2, 3, 4);
    

    这是这个想法的一个实现:

    // Get an array of parameter names from a function
    Function.parameters = function(f) {
        // Find the parameter list in f.toString()
        var m = /function[^\(]*\(([^\)]*)\)/.exec(f.toString());
        if (!m) {
            throw new TypeError("Invalid function in parameters");
        }
    
        var params = m[1].split(',');
        for (var i = 0; i < params.length; i++) {
            // trim possible spaces
            params[i] = params[i].replace(/^\s*|\s*$/g, '');
        }
        return params;
    };
    
    // Convert f to a function that accepts named parameters
    Function.withNamedParameters = function(f) {
        var params = Function.parameters(f);
        return function(args) {
            var argsArray = new Array(params.length);
            for (var i = 0; i < params.length; i++) {
                argsArray[i] = args[params[i]];
            }
            return f.apply(this, argsArray);
        };
    };
    

    我有一个稍微更灵活的实现,它可以向另一个方向发展。( Function.withPositionalParameters 在Github上: http://gist.github.com/132782 .

        4
  •  7
  •   Romain Linsolas    15 年前

    我认为这基本上是用于调试目的…

        5
  •  4
  •   Community Michael Schmitz    7 年前

    阐述 idea raised above by James Westgate ,下面是一个使用 toString() 要创建、分派和接收Web工作者,请执行以下操作:

    /*
     * @param fun the function to carry out in the web worker
     * @param mes the message to send to the web worker
     * @param com the function to do on completion
     * creates, dispatches & receives a web worker
     */
    function wor(fun, mes, com) {
       var wor = new Worker(URL.createObjectURL(new Blob([
             'self.onmessage = ' + fun.toString()], {
             type: 'application/javascript'
       })));       
       wor.postMessage(mes);
       wor.onmessage = com;
    }
    

    通过将函数转换为字符串,我们可以使用它在对象URL中创建一个函数,然后在接收数据时解析并执行该函数。

        6
  •  3
  •   T.J. Crowder    15 年前

    一个现实世界的例子是 Prototype ,它使用这个来确定子类中方法的参数的名称,以查看它是否应该执行它的特殊操作。 superclass handling 东西(包括特殊的争论 $super )

        7
  •  3
  •   OrangeDog    13 年前

    CouchDB的视图定义 map reduce 作为字符串。与 function.toString 您可以将这些函数作为适当的函数编写(这样,IDE/语法检查器可以帮助您),然后在插入它们时将它们转换为字符串。

        8
  •  3
  •   alex urdea    12 年前

    AngularJS使用此模式注入其内置服务。您只需使用服务名(前缀为“$”)作为函数的参数-例如:“$http”。

    See the exact usage on Github.

        9
  •  3
  •   Barney    11 年前

    javascript源中的多行字符串。

    如上所述 this blog post by @tjanczuk 在javascript中最大的不便之一是多行字符串。但你可以利用 .toString() 以及多行注释的语法( /* ... */ )产生相同的结果。

    通过使用 following function :

    function uncomment(fn){
      return fn.toString().split(/\/\*\n|\n\*\//g).slice(1,-1).join();
    };
    

    然后可以按以下格式传递多行注释:

    var superString = uncomment(function(){/*
    String line 1
    String line 2
    String line 3
    */});
    

    在原文中,注意到 Function.toString() 's behavior is not standarded and so implementation discrete_ a Fiddle I wrote seems to work on every browser I have available to me (Chrome 27、Firefox 21、Opera 12、Internet Explorer 8)。

        10
  •  2
  •   DuckMaestro    13 年前

    我相信Visual Studio的IntelliSense使用它来定位和分析可选的 XML Code Comments 对于任何此类文件化功能,如:

    function areaFunction(radiusParam)
    {
        /// <summary>Determines the area of a cicle based on a radius parameter.</summary>
        /// <param name="radius" type="Number">The radius of the circle.</param>
        /// <returns type="Number">Returns a number that represents the area.</returns>
        var areaVal;
        areaVal = Math.PI * radiusParam * radiusParam;
        return areaVal;
    }
    

    可以想象,您可以在运行时自己分析这个问题,以便随时提供文档或补充未处理异常的详细信息。

        11
  •  1
  •   DuxPrime    10 年前

    在多窗口Web应用程序中,如果需要在以后要执行的窗口之间共享一个函数,但不能保证该函数的所有者(在其中定义的窗口)在执行时是活动的,则可以使用 toString() ,将其存储到相关窗口,然后调用 eval() 在以后的执行时间。当然,使用 表达式() 有自己的缺点,但这似乎是一个合法的用例(我们需要重新调用脚本解析引擎,将序列化函数转换回可执行代码)。

    在这种情况下,这是避免访问被拒绝错误的唯一可靠方法。这里的关键是执行上下文现在变成了我们调用的窗口 表达式() 函数最初定义的范围,而不是范围,因此必须注意不要依赖函数直接范围之外的变量。

        12
  •  0
  •   Joshua    15 年前

    除了将函数的内容作为字符串获取,或者确保 类型 无论您使用的是字符串(用于非强制比较),请检查可使用的可选基数参数。

    基数 可选。指定将数值转换为字符串的基数。此值仅用于数字。

    var a = 16;
    a.toString(2)    // returns "10000"
    a.toString(4)    // returns "100"
    a.toString(8)    // returns "20"
    a.toString(16)   // returns "10"
    a.toString(32)   // returns "g"
    

    下面的示例说明了使用带基数参数的ToString方法。下面显示的函数的返回值是基数转换表。

    function CreateRadixTable (){
       var s, s1, s2, s3, x;                    //Declare variables.
       s = "Hex    Dec   Bin \n";               //Create table heading.
       for (x = 0; x < 16; x++)                 //Establish size of table
       {                                        // in terms of number of
          switch(x)                             // values shown.
          {                                     //Set intercolumn spacing.
             case 0 : 
                s1 = "      ";
                s2 = "    ";
                s3 = "   ";
                break;
             case 1 :
                s1 = "      ";
                s2 = "    ";
                s3 = "   ";
                break;
             case 2 :
                s3 = "  ";
                break;
             case 3 : 
                s3 = "  ";
                break;
             case 4 : 
                s3 = " ";
                break;
             case 5 :
                s3 = " ";
                break;
             case 6 : 
                s3 = " ";
                break;
             case 7 : 
                s3 = " ";
                break;
             case 8 :
                s3 = "" ;
                break;
             case 9 :
                s3 = "";
                break;
             default: 
                s1 = "     ";
                s2 = "";
                s3 = "    ";
          }                                     //Convert to hex, decimal & binary.
          s += " " + x.toString(16) + s1 + x.toString(10)
          s +=  s2 + s3 + x.toString(2)+ "\n";
    
       }
       return(s);                               //Return entire radix table.
    }
    
        13
  •  0
  •   James Westgate    11 年前

    可以用作对Web工作者进行编码的一种方法,而不必将函数放在单独的文件中。

        14
  •  0
  •   1j01    10 年前

    可以使用函数字符串化在生成的页面中包含函数,并在源中突出显示函数的语法。 我也用coffeescript完成了这项工作,用coffeescript编写并突出显示函数,但由于它被视为一个javascript函数…是一个。或者因为它是在编译其余的coffeescript时编译成的。

    See this on github:

            error_handling = ->
                d = document.createElement "div"
                d.className = "error bubble script-error"
                window.onerror = (error)->
                    document.body.appendChild d
                    d.style.position = "absolute"
                    d.style.borderRadius = d.style.padding = 
                    d.style.bottom = d.style.right = "5px"
                    d.innerText = d.textContent = error
    
            body += """
                <script>~#{error_handling}()</script>
                <style>
                    .error {
                        color: red;
                    }
                    .error.bubble {
                        background: rgba(255, 0, 0, 0.8);
                        color: white;
                    }
                    body {
                        font-family: Helvetica, sans-serif;
                    }
                </style>
            """
    
        15
  •  0
  •   ibigbug    9 年前

    断言参数不为空

    exports.warnNull = function() {
      var func = arguments.callee.caller
      var args = func.toString().match(/function\s*\w*\((.*?)\)\s*/)[1].split(',').map(Function.prototype.call.bind(String.prototype.trim))
      var params = Array.prototype.slice.call(arguments)
      for (var i = 0; i < params.length; i ++) {
        if (!params[i]) {
          console.warn(gutil.colors.yellow('缺少变量 : ' + args[i]))
        }
      }
    }
    

    缠绕长字符串

    exports.controller = function(){
    /*
    app.controller('{{ controllerName }}', function({{ injects }}) {
      // ...
    })
    */
    }.toString().slice(16, -4)