我在JavaScript中注意到,如果您定义一个函数,比如myfunction()
,然后调用myfunction.toString()
,您将获得该函数的源文本。这有什么有趣的/现实世界的用途吗?
答案 0 :(得分:14)
好吧,您可以使用它轻松重新定义函数:
function x() { alert('asdf'); }
eval(x.toString().replace('asdf','hello'));
x();
这将提醒字符串“hello”而不是字符串“asdf”。
这可能很有用。另一方面,由于难以维护代码,自修改代码常常不受欢迎......
答案 1 :(得分:11)
这是一个老问题,但这是我的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客户端的数据。
答案 2 :(得分:8)
我用它来自动生成函数的命名参数版本。例如,如果您有一个功能
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);
};
};
我有一个稍微灵活一点的实现,可以在GitHub上转向另一个方向(Function.withPositionalParameters
):http://gist.github.com/132782。
答案 3 :(得分:7)
我认为这主要用于调试目的......
答案 4 :(得分:4)
详细阐述idea raised above by James Westgate,这是一个使用toString()
创建,调度和发布的例子。接收网络工作者:
/*
* @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中创建一个函数,然后对其进行解析和解析。在接收数据时执行。
答案 5 :(得分:3)
一个真实世界的例子在Prototype中,它使用它来确定子类中方法的参数名称,以查看它是否应该执行其特殊的superclass handling内容(涉及特殊参数) $super
)。
答案 6 :(得分:3)
CouchDb的视图定义将map
和reduce
作为字符串。使用function.toString
,您可以将这些函数编写为正确的函数(因此IDE /语法检查器可以帮助您),然后在插入时将它们转换为字符串。
答案 7 :(得分:3)
Angular JS使用此模式注入其内置服务。您需要做的就是使用服务名称(以“$”为前缀)作为函数的参数 - 例如:“$ http”。
答案 8 :(得分:3)
如this blog post by @tjanczuk中所述,Javascript中的一个巨大不便之处是多行字符串。但您可以利用.toString()
和多行注释(/* ... */
)的语法来生成相同的结果。
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()
的行为不是标准化的,因此是实现离散的 - 推荐的用法是针对Node.js(可以依赖V8解释器);但是,a Fiddle I wrote seems to work on every browser I have available to me(Chrome 27,Firefox 21,Opera 12,Internet Explorer 8)。
答案 9 :(得分:2)
我相信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;
}
可以想象,您可以在运行时自己解析这个问题,随意提供文档或补充未处理异常的详细信息。
答案 10 :(得分:1)
在多窗口Web应用程序中,如果您需要在Windows之间共享一个函数以便稍后执行,但不能保证该函数的所有者(它所定义的窗口)将是在执行时生效,您可以使用toString()
序列化该函数,将其存储到相关窗口,并在以后的执行时间/时间调用eval()
。当然,使用eval()
有自己的瑕疵,但这似乎是一个合法的用例(我们需要重新调用脚本解析引擎以将序列化函数转换回可执行代码)。
这是在这种情况下唯一没有获得访问被拒绝错误的确定方法。这里的问题是执行上下文现在变成了我们从eval()
调用的窗口,而不是函数最初定义的范围,因此必须注意不要依赖函数之外的变量&#39;直接范围。
答案 11 :(得分:0)
除了将函数的内容作为字符串获取,或确保您正在使用的任何字符的类型是一个字符串(用于非强制性比较)之外,请查看可选项可以使用的基数参数。
radix 可选。指定用于将数值转换为字符串的基数。该值仅用于数字。
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"
以下示例说明了使用带有radix参数的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.
}
答案 12 :(得分:0)
可以用作编写Web Workers的方法,而无需将函数放在单独的文件中。
答案 13 :(得分:0)
您可以利用函数字符串化在生成的页面中包含一个函数,并在源代码中突出显示函数。 我也用CoffeeScript完成了这个,用函数编写并突出显示为CoffeeScript,但是因为它是...而被视为JavaScript函数。或者因为在编译CoffeeScript的其余部分时将其编译为一个。
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>
"""
答案 14 :(得分:0)
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)
答案 15 :(得分:0)
toString
是一种序列化方法。在某些情况下,我们需要将功能逻辑存储到数据库或通过互联网传输的存储中。也是描述“如何做某事”的一种数据。