从new Function创建函数联想到MVC模式
我们知道任何一个自定义函数都是Function构造器的实例,所以我们可以通过new Function的方式来创建函数,使用语法很简单,
new Function(形参1, 形参2, ..., 形参N, 函数体)
注意,里面的参数全部是以字符串的形式呈现。比如一个简单的例子——要求写一个函数, 求两个数字中最大的数字, 并返回最大数字。如果按照声明式函数的思想来写,可能会是这样
function max(a,b){ return a > b ? a : b; }
但我们转化到函数构造器(new Function)的方式去写,会是这样
var fn = new Function('a','b','return a>b?a:b'); var max = fn(1,2); max; //2
当然,看到这里,我们并没有看出以函数构造器的方式创建函数相对于声明式函数来说具有某方面的优势。但我们继续看下一个稍复杂点的例子:
写一个函数, 传入任意个参数, 求最大值 。我们以这两种方法写出它。
function max() { var a = arguments; var m = a[0]; for (var i = 0; i < a.length; i++) { if (m < a[i]) { m = a[i]; } } return m; } var res = max(1, 5, 16, 3,2); console.log(res); //16
var fn = new Function( 'var a = arguments;'+ 'var m = a[0];'+ 'for (var i = 0; i < a.length; i++) {'+ ' if (m < a[i]) {'+ ' m = a[i];'+ ' }'+ '}'+ 'return m;' ); var res = fn(1,5,16,3,2); console.log(res); //16
然后我们可以将上面的代码优化一下,将函数体抽出来放在独立的一个script标签中。
<script id="control"> /* var max = arguments[0]; for(var i=0;i<arguments.length;i++){ if(arguments[i]>max){ max = arguments[i]; } } return max; */ </script> <script> var fn = new Function( document.getElementById('control').innerHTML .trim() .replace('/*', '') .replace('*/', '') ) var foo = fn(1,2,10,4) console.log(foo) //10 </script>
这样写的好处是当需要更改函数方法时,只需要在第一个script标签里面改,并不影响下面script标签。
再补充一点关于函数构造器的作用域的问题,它跟声明式函数的不同是,声明式函数内部可以访问外部或者说外函数的局部变量,但是函数构造器却不能。
var globalVal = 'global' function fn(){ var localVal = 'local'; function foo(){ console.log(typeof localVal,typeof globalVal); } foo() } fn() //string string
var globalVal = 'global' function fn(){ var localVal = 'local'; new Function('console.log(typeof localVal,typeof globalVal);')(); } fn() // undefined global