js定义函数的三种方法及区别
1 函数定义: 2 function test(){}; 3 函数表达式|匿名函数 4 var test = function(){}; 5 构造函数 6 var test=new Function('a','b', '函数体');
function test(a,b) { console.log(a+b) }; var testTwo=function (a,b) { console.log(a*b); } var testThree=new Function('a','b','console.log(a-b)'); test(5,4);//9 testTwo(5,4);//20 testThree(5,4)//1
以上就是三种方法定义的函数如何使用。
下面谈一下三种方法的区别。我们还是从代码入手来看。
test(5,4); //9 function test(a,b) { console.log(a+b) }; testTwo(5,4);//Uncaught TypeError: testTwo is not a function var testTwo=function (a,b) { console.log(a*b); } testThree(5,4);//Uncaught TypeError: testThree is not a function var testThree=new Function('a','b','console.log(a-b)');
上面这段代码只是改变了函数的调用位置,但是结果却产生改变,除了test函数调用成功之外,另外两个函数都报错了,那么第一个区别就是 通过函数定义语句来定义的函数可以在函数体定义之前来调用,另外两种不行。下面我们来简单聊一下为什么会产生这种不同。首先,了解一下js在执行代码之前的一些步骤。
1 语法分析,(引擎检查你的代码有没有什么低级的语法错误 比如定义一个非法变量等等。。。)
2 预编译, (简单的理解就是在内存中开辟一些空间,来存放你代码中定义的这些变量和函数。。。)一般在函数体执行之前。
3 解释执行 (开始执行你的代码)。
本次我们重点来说一下 预编译这个步骤
我们的代码被预编译的时候,首先会检测我们的代码中是否有var 关键字和function关键字,如果有var则首先给var定义的变量赋值一个undefined,就比如下面的代码;
var a=123;//我们代码处始定义的形态 // 代码预编译的时候呈现的形态 a=undefined; a=123;
这就解释了为什么当我们用 字面量表达式 定义的函数不能在函数体定义之前调用的原因。
testTwo(5,4);//当程序执行到这一步的时候,此时的testTwo为undefined,所以会报以上错误 var testTwo=function (a,b) { console.log(a*b); } //如果我们在这个位置调用testTwo,那么函数变量经历了上面的赋值操作,已经将函数体赋给变量,所以代码可以正常执行
那么,当程序预编译遇到function关键字时,是将整个函数体直接赋值给function定义的函数名,所以,可以在函数定义之前就可以调用。
其实通过 字面量表达式和Function() 构造函数定义的是一个匿名函数,只不过同过=操作符赋值给了定义的变量而已。