JS中函数的创建有2种方式:函数声明和函数表达式
//function definition (also called function declaration)
function func1() {
console.log("Hello World1");
}
func1();
// function expression
var func2 = function (){
console.log("Hello World2");
};
func2();
第一种方式即为函数声明也叫函数定义,在js执行时,会自动把此种方式声明的函数添加到全局作用域,所以对此方式创建的函数的调用可以在函数之前也可在函数之后;
第二种方式为“函数表达式”,与第一种方式的区别是对此种方式创建的函数的调用必须在函数之后,因为js解析时会把fun2添加到全局作用域,此时fun2只是一个指向函数的指针,并不具有实际内容,只有在执行到此函数时候,才会把具体的代码添加上去,此时的函数便可称为匿名函数。
var a = 10;
var f = function(){//code...};
f(); // 调用函数f
此时f指向后边的匿名函数,通过f()即可调用后边的函数,那我们可不可以直接调用呢?
//函数(function),括弧(paren),语法错误(SyntaxError)
function(){console.log("Hello World3");}();
// output: Uncaught SyntaxError: Unexpected token (
执行报错,为什么呢?我们可以观察下2种方式创建的函数的语法:
函数定义: function funcName(){//code...} ;
函数表达式: function [funcName](){//code...};
可以看到2种方式的语法差别不大,那js解析器是如何区分的呢?
根据JavaScript语法,以function开始的语句会被解析为函数定义,而函数定义是需要有函数名的,且需要通过函数名来执行,此处的写法显然不符合语法规范,若想要成功执行,就需要让js解析器将此解析为函数表达式,那如何达到此目的呢?
var a = 1;
此处是一个简单的函数表达式,由此我们可以想到可以在语句前边加一个合适的运算符,由于右边为一个函数对象操作数(JS语句),所以我们可以使用操作数可以为对象的一元运算符
! function(){console.log("Hello World2");}(); //Hello World2
+ function(){console.log("Hello World3");}(); //Hello World3
- function(){console.log("Hello World4");}(); //Hello World4
~ function () { console.log("Hello World5"); } (); //Hello World5
delete function(){console.log("Hello World6");}(); //Hello World6
void function(){console.log("Hello World7");}(); //Hello World7
// 还有一个情况,使用new关键字,也可以用,但我不确定它的效率
// http://twitter.com/kuvos/status/18209252090847232
new function () { /* code */ }
new function () { /* code */ } () // 如果需要传递参数,只需要加上括弧()
以上均可实现让js解释器以创建函数表达式的方式创建函数,实际使用中,以“!“居多。
另外一种更常用的写法, 也就是JQuery的用法, 是用圆括号作为分组操作符来让该执行函数语句被强制解释为以函数表达式的方式来创建这个匿名函数.
// 第一种写法 ()分组运算符的内部代码只能是表达式, 这里将以函数表达式的方式创建并返回匿名函数
(function(){/* code... */ };)();
// 第二种写法 直接将最顶层的括号内部当做表达式创建并运行该匿名函数
(function(){...}(););
(function(){console.log("Hello World6");})(); //Hello World6
(function(){console.log("Hello World6");}()); //Hello World6
自执行匿名函数和立即执行的函数表达式区别
这篇帖子里,我们一直叫自执行函数,确切的说是自执行匿名函数(Self-executing anonymous function),但英文原文作者一直倡议使用立即调用的函数表达式(Immediately-Invoked Function Expression)这一名称,作者又举了一堆例子来解释:
// 这是一个自执行的函数,函数内部执行自身,递归
function foo() { foo(); }
// 这是一个自执行的匿名函数,因为没有标示名称
// 必须使用arguments.callee属性来执行自己
var foo = function () { arguments.callee(); };
// 这可能也是一个自执行的匿名函数,仅仅是foo标示名称引用它自身
// 如果你将foo改变成其它的,你将得到一个used-to-self-execute匿名函数
var foo = function () { foo(); };
// 有些人叫这个是自执行的匿名函数(即便它不是),因为它没有调用自身,它只是立即执行而已。
(function () { /* code */ } ());
// 为函数表达式添加一个标示名称,可以方便Debug
// 但一定命名了,这个函数就不再是匿名的了
(function foo() { /* code */ } ());
// 立即调用的函数表达式(IIFE)也可以自执行,不过可能不常用罢了
(function () { arguments.callee(); } ());
(function foo() { foo(); } ());
转自http://www.cnblogs.com/ayning/p/4113314.html
相关资料参考:https://blog.csdn.net/yaojxing/article/details/72784774