javascript 中几种匿名函数的写法

//这样代表是一个"函数字面量":首先声明一个函数对象,然后执行它,这是最常见的写法
(function() { alert('test');})();

//优先表达式:由于Javascript执行表达式是从圆括号里面到外面,所以可以用圆括号强制执行声明的函数。
(function(){ alert('test');}());

//Void操作符:用void操作符去执行一个没有用圆括号包围的一个单独操作数,据说这种写法效率最高。
void function(){ alert('test');}();

//以下几种前面带符号的只能算是一种技巧,只不过中把"函数声明"让JavaScript解释成"函数表达式"
~(function(){ alert('test');})();
+function(){ alert('test');}(); 
-function(){ alert('test');}();
~function(){ alert('test');}();
!function(){ alert('test');}();
~!(function(){ alert("run!") })();
~+-!(function(){ alert("test"); })();

//让函数表达式通过call()或者是apply()调用"函数表达式"自身
(function(){ alert("test");}).call();
(function(){ alert("test");}).apply();

//delete本意是用来删除对象的属性,但用在这里就相当于把"函数声明"让JavaScript解释成"函数表达式"
delete (function(){ alert("test");})();


AST(抽象语法树)


从作用上看,作用都是创建一个函数并调用之。
那么为什么要创建一个函数并立即调用呢,我想大多数是因为javascript的代码默认在全局环境下执行,在此声明的所有变量都会变成全局变量,这很容易导致全局对象的污染。因此我们不得不找一个办法来隔离这些变量,而函数正好会创建属于自己的作用域,因此创建一个匿名函数并立即调用(有称此为IIFE-Immediately Invoked Function Exprssion-立即调用的函数表达式)成为了一种几乎公认的方案。
随后,又为什么要这么写呢?原因自然是在javascript中有2个语法都与function关键字有关,分别是:
函数定义:function FunctionName(FormalParameterList) { FunctionBody }
函数表达式:function [FunctionName](FormalParameterList) { FunctionBody }
从语法的定义上看,这两者几乎是一模一样的(唯一的区别是函数表达式可以省略函数名称),那么就解释器而言,当遇到这个结构的语句时,判定为函数表达式还是函数定义呢?
就javascript的语法而言,如果一条语句是以function关键字开始,那么这段会被判定为函数定义。而函数定义是不能被立即执行的,这无疑会导致语法的错误(SyntaxError),因此就必须有一个办法,使解析器可以将之识别为函数表达式。
前面已经说到,解析器识别函数定义的条件是以function关键字开始,那么自然,只要在function关键字的前面有任何其他的元素,就会从函数定义转变为函数表达式,以下方法都是可以的,这个大家都知道:
~function() {}();
!function() {}();
void function() {}();

但是这几个方法都有一个特点,就是看起来很别扭,所以现在为止,以括号包裹成了比较公认的方案。
回到正题,括号包裹同样有2个方式:(function() {})();和(function(){}());
他们的共通点是:都有括号。而括号在javascript中有2种作用:确立运算优先级,以及分组运算符(es5.github.com/#),从代码上看,显然没有进行数学或逻辑运算,因此我认为这里的括号属于分组运算符
根据标准,分组运算符的作用是:

Return the result of evaluating  Expression. This may be of type Reference. 

返回评估括号中的表达式的结果。结果可能是Reference类型。
抛开像Reference类型这种词汇,这里的一个关键词应当是“ 评估 ”(对evaluate的翻译一直把握不好,姑且这么叫吧),但是关于分组运算符,又有一个很重要的下文:
This algorithm does not apply GetValue to the result of evaluating Expression.

这个算法不会对估算的结果使用GetValue。
有很多专用的名词,看起来确实复杂,简而言之,使用括号运算符本身不会让括号中的代码立即执行,只有当括号包含的这个“分组”参与其他运算时,才会执行。因此,(function(){})()这个语句,其实是首先用分组运算符评估了一个 函数表达式 ,随后参与“函数调用”。而(function(){}())这个语句,则是用分组运算符评估了一个 函数调用 ,随后由于语句的结束而被执行。从语句上来说有细微的差距,当然就结果而言是 一样 的,最初的AST分析也可以证实这点,分组运算符在AST中完全没有体现出来。



资料地址:http://www.dewen.org/q/1684 

http://www.zhihu.com/question/20292224


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值