js有的时候会出现,将方法名称作为一个参数传递到方法中,然后再调用。这个时候,就有可能会出现问题。

场景一

<html>
<head>
<title>js fucntion name as the paramter</title>
</head>
<body>

<input type="button" name="button" value="button" onclick="passParam(fname);">button content</button>
</body>
<script type="text/javascript" src="jquery-1.8.2.min.js"></script>
<script type="text/javascript">
function passParam(param) {
alert(typeof param);
param("sssssss");
}
function fname(s) {
alert("fname:(" + s + ")");
}
</script>
</html>

这种情况,没有任何问题,可以直接调用。typeof  param 结果为 function

场景二

<html>
<head>
<title>js fucntion name as the paramter</title>
</head>
<body>

<input type="button" name="button" value="button" onclick="passParam('fname');">button content</button>
</body>
<script type="text/javascript" src="jquery-1.8.2.min.js"></script>
<script type="text/javascript">
function passParam(param) {
alert(typeof param);
param("sssssss");
}
function fname(s) {
alert("fname:(" + s + ")");
}
</script>
</html>

和场景一唯一不同的就是参数使用引号包裹了下,就这么一点点差别,结果却是完全不同。typeof param 的结果为string .最终的运行结果为:TypeError: param is not a function。这样操作,js尝试运行的是param而不是param对应的值fname。

这个时候有同学就说,使用eval,eval将任何的string作为code来运行。

场景三

<html>
<head>
<title>js fucntion name as the paramter</title>
</head>
<body>

<input type="button" name="button" value="button" onclick="passParam('fname');">button content</button>
</body>
<script type="text/javascript" src="jquery-1.8.2.min.js"></script>
<script type="text/javascript">
function passParam(param) {
alert(typeof param);
eval("param(\"sssssss\")");
}
function fname(s) {
alert("fname:(" + s + ")");
}
</script>
</html>

结果依然和场景二一样。这个时候会有同学说:“不对,不对,你的eval使用方法错了”。然后这个同学给出了TA自己eval方法的实现方式

场景四

<html>
<head>
<title>js fucntion name as the paramter</title>
</head>
<body>

<input type="button" name="button" value="button" onclick="passParam('fname');">button content</button>
</body>
<script type="text/javascript" src="jquery-1.8.2.min.js"></script>
<script type="text/javascript">
function passParam(param) {
alert(typeof param);
eval(param + "(\"sssssss\")");
}
function fname(s) {
alert("fname:(" + s + ")");
}
</script>
</html>

运行,ok很好。正确执行了相应的方法,问题得到了解决。

大家都知道eval的功能异常的强大,强大到我们不敢、也不能随随便便使用它。那么我们能不能不适用eval方法的实现方式哪?大家开动脑筋,想了一会,这个时候有另外一个同学兴奋的说有了,可以使用setTimeout间接调用

场景五

<html>
<head>
<title>js fucntion name as the paramter</title>
</head>
<body>

<input type="button" name="button" value="button" onclick="passParam('fname');">button content</button>
</body>
<script type="text/javascript" src="jquery-1.8.2.min.js"></script>
<script type="text/javascript">
function passParam(param) {
alert(typeof param);
setTimeout(param + "(\"ssssss\")",0);
}
function fname(s) {
alert("fname:(" + s + ")");
}
</script>
</html>

运行结果很好。那么是否还有其他方法可以实现这个哪?大家又陷入了深思。。

“window,可以使用当前window对象。我们定义的所有元素都会包含在window对象里面。”  这个时候一个默默无闻的同学终于开口了。

场景六

<html>
<head>
<title>js fucntion name as the paramter</title>
</head>
<body>

<input type="button" name="button" value="button" onclick="passParam('fname');">button content</button>
</body>
<script type="text/javascript" src="jquery-1.8.2.min.js"></script>
<script type="text/javascript">
function passParam(param) {
alert(typeof param);
// find object
var fn = window[param];
// is object a function?
if (typeof fn === "function") fn("sssss");
}
function fname(s) {
alert("fname:(" + s + ")");
}
</script>
</html>

运行下,非常棒。

这个方法还可以优化下。

场景七

<html>
<head>
<title>js fucntion name as the paramter</title>
</head>
<body>

<input type="button" name="button" value="button" onclick="passParam('fname');">button content</button>
</body>
<script type="text/javascript" src="jquery-1.8.2.min.js"></script>
<script type="text/javascript">
function passParam(param) {
alert(typeof param);

<div class="post-message " dir="auto" data-role="message">

if(param in window && typeof window[param] == 'function') window[param]("sssss");
}
function fname(s) {
alert("fname:(" + s + ")");
}
</script>
</html>

不错不错。

还可以再优化,可以抽象出来

/**
 * 根据字符串类型的方法名 调用对应的js function
 * executeFunctionByName("My.Namespace.functionName", window, arguments);
 * executeFunctionByName("Namespace.functionName", My, arguments);
 *
 * @param functionName
 * @param context
 * @returns {*}
 */

var smvcJSUtil = {
    executeFunctionByName: function (functionName, context /*, args */){ //对调 functionName function
        var args = [].slice.call(arguments).splice(2);
        var namespaces = functionName.split(".");
        var func = namespaces.pop();
        for (var i = 0; i < namespaces.length; i++) {
            context = context[namespaces[i]];
        }
        return context[func].apply(this, args);
    },
    functionExistsByName: function(functionName) { //判断制定字符串是否为function
        return functionName in window && typeof window[functionName] == 'function'
    }
};

方法越来越好了。。我们原来的问题不但解决了,而且还因此学到了很多知识。

参考:

http://www.sitepoint.com/call-javascript-function-string-without-using-eval/

http://stackoverflow.com/questions/359788/how-to-execute-a-javascript-function-when-i-have-its-name-as-a-string