在JS的学习中遇到一些JS函数声明的问题,找了一些资料学习之后,有了自己的一些初步的认识。
首先,了解函数声明,函数声明:就是使用关键字function,与指定的某个字段组成函数,作为函数声明。例如:
function funName(){
//
}
这就是简单的函数函数声明了。
接下来就是函数表达式,函数表达式:将关键字function声明的函数,但不指定字段作为函数名,形成匿名函数,赋值给某个变量。例如:
var funName=function(){
}
这就是函数表达式了。匿名函数赋值给变量成为函数表达式,该过程会创建函数。同样匿名函数同样可以作为赋值给某个监听的事件,成为事件处理程序,创建闭包。这是比较官方的说法。当然,将匿名函数作为参数时,往往可以起到不错的效果,举个例子就是,例如:
function funName( p1,p2,callback){
if(p1>p2){
callback(p1-p2);
}
}
funName(10,8,function(e){
//获取到返回值
console.log(e); // 值为2
});
在JS解析中:函数声明会提升。即在预解析的时候,函数声明不但会被声明,同时也会定义。
这就是为什么我们调用function声明一个函数的时候,function funName(){
}
无论是在函数声明之前还是在函数声明之后,都可以有效的执行这个函数。
但是在函数表达式的中,不会这样。
var funName =function(){
}
在JS预解析的时候,只会预解析等号左边 var 声明的变量,不会定义右边的函数。当我们在
funName(“hello world”); //报错
var funName =function(e){
alert(e);
}
funName("你好!!!"); //这里不会报错.
最后,还有一个立即函数:
( function(){
…
} )()
( function (){
…
} () )
是两种javascript立即执行函数的常见写法。
这两种立即执行函数的写法,最初我以为是一个括号包裹匿名函数,并后面加个括号立即调用函数,当时不知道为什么要加括号,后来明白,要在函数体后面加括号就能立即调用,则这个函数必须是函数表达式,不能是函数声明。
(function(){})(); 是 把函数当作表达式解析,然后执行解析后的函数相当于var a = function(){}; a(); a得到的是函数。
(function(){}()); 是把函数表达式和执行当作语句直接执行、相当于 var a = function(){}(); a得到的是结果。
最终结果是一样的。()只是起了 自执行的作用,和 () 一样的还有很多
例如:
(function(a){
console.log(a); //firebug输出123,使用()运算符
})(123);
(function(a){
console.log(a); //firebug输出1234,使用()运算符
}(1234));
!function(a){
console.log(a); //firebug输出12345,使用!运算符
}(12345);
+function(a){
console.log(a); //firebug输出123456,使用+运算符
}(123456);
-function(a){
console.log(a); //firebug输出1234567,使用-运算符
}(1234567);
varfn=function(a){
console.log(a); //firebug输出12345678,使用=运算符
}(12345678)
可以看到输出结果,在function前面加!、+、 -甚至是逗号等到都可以起到函数定义后立即执行的效果,而()、!、+、-、=等运算符,都将函数声明转换成函数表达式,消除了javascript引擎识别函数表达式和函数声明的歧义,告诉javascript引擎这是一个函数表达式,不是函数声明,可以在后面加括号,并立即执行函数的代码。
加括号是最安全的做法,因为!、+、-等运算符还会和函数的返回值进行运算,有时造成不必要的麻烦。
不过这样的写法有什么用呢?
javascript中没用私有作用域的概念,如果在多人开发的项目上,你在全局或局部作用域中声明了一些变量,可能会被其他人不小心用同名的变量给覆盖掉,根据javascript函数作用域链的特性,可以使用这种技术可以模仿一个私有作用域,用匿名函数作为一个“容器”,“容器”内部可以访问外部的变量,而外部环境不能访问“容器”内部的变量,所以( function(){…} )()内部定义的变量不会和外部的变量发生冲突,俗称“匿名包裹器”或“命名空间”。
JQuery使用的就是这种方法,将JQuery代码包裹在
( function (window,undefined){…jquery代码…} (window)
中,在全局作用域中调用JQuery代码时,可以达到保护JQuery内部变量的作用。