真实的输出参数的主要优点是可以直接修改调用者作用域内一个或多个标量变量。在其他答案中提出的方法中,只有回调函数满足此要求:
function tryparse_int_1(s, cb)
{ var res = parseInt(s);
cb(res);
return !isNaN( res );
}
function test_1(s)
{ var i;
if( tryparse_int_1( s, x=>i=x ) )
console.log(`String "${s}" is parsed as integer ${i}.`); else
console.log(`String "${s}" does not start with an integer.`);
}
test_1("47");
test_1("forty-seven");
在这种情况下,传递每个输出参数需要额外的五个字符来将其标识符包装到匿名设置函数中。它既不易读也不易频繁输入,因此可以利用脚本语言最有趣的特性之一——执行字符串作为代码的能力。
以下示例实现了上面整数解析函数的扩展版本,现在具有两个输出参数:结果整数和指示它是否为正的标志:
function out_lit(v)
{ var res;
if( typeof(v) === "string" )
res = '"' + v.split('\"').join('\\\"') + '"'; else
res = `${v}`;
return res;
}
function out_setpar(col, name, value)
{ if( col.outs == undefined ) col.outs = [];
col.outs[name] = value;
}
function out_setret(col, value)
{ col.ret = value; }
function out_ret( col )
{ var s;
for(e in col.outs)
{ s = s + "," + e + "=" + out_lit( col.outs[e] ); }
if( col.ret != undefined )
{ s = s + "," + out_lit( col.ret ); }
return s;
}
function tryparse_int_2
( s,
int,
pos
)
{ var res;
var col;
res = parseInt(s);
col = [];
out_setpar( col, int, res );
out_setpar( col, pos, res > 0 );
out_setret( col, !isNaN( res ) );
return out_ret( col );
}
在这个版本中,传递每个输出参数需要在其标识符周围添加两个额外的字符以将其嵌入字符串文字中,每次调用需要六个字符来评估结果。
function test_2(s)
{ var int;
var pos;
if( !eval( tryparse_int_2( s, "int", "pos" ) ) )
{ console.log(`String "${s}" does not start with an integer.`); }
else
{ if( pos ) adj = "positive";
else adj = "non-positive";
console.log(`String "${s}" is parsed as a ${adj} integer ${int}.`);
}
}
test_2( "55 parrots" );
test_2( "-7 thoughts" );
test_2( "several balls" );
上面测试代码的输出为:
String "55 parrots" is parsed as a positive integer 55.
String "-7 thoughts" is parsed as a non-positive integer -7.
String "several balls" does not start with an integer.
然而,这个解决方案有一个缺陷:它无法处理非基本类型的返回。
也许更清晰的方法是模拟指针:
function makeref(v)
{ return `var $${v} = {set _(val){${v}=val;},get _() {return ${v};}}`; }
function sqrt2
( value,
$root ,
$errmsg
)
{ if( typeof( value ) !== "number" )
{ $errmsg._ = "value is not a number.";
return false;
}
if( value < 0 )
{ $errmsg._ = "value is negative.";
return false;
}
$root._ = Math.sqrt(value);
return true;
}
以下是测试代码:
function test(v)
{ var resmsg;
var root ; eval( makeref( "root" ) );
var errmsg; eval( makeref( "errmsg" ) );
if( sqrt2(v, $root, $errmsg) ) resmsg = `Success: ${root}`;
else resmsg = `Error: ${errmsg}`;
console.log(`Square root of ${v}: ` + resmsg );
}
test("s" );
test(-5 );
test( 1.44);
打印:
Square root of s: Error: value is not a number.
Square root of -5: Error: value is negative.
Square root of 1.44: Success: 1.2
通过这种方法创建的“指针”可以在其他函数中重复使用,并且可以在同一函数的后续调用中重复使用。例如,您可以定义一个附加字符串的函数:
function append($s, sep, val)
{ if( $s._ != '' ) $s._ += sep;
$s._ += val;
}
并且这样使用:
const sep = ", "
var s; eval( makeref("s") );
s = '';
append( $s, sep, "one" );
append( $s, sep, "two" );
append( $s, sep, "three" );
console.log( s );
它将打印:
one, two, three