ECMAScriptJavaScript函数的余定义方法

缘起

javascript和任何编程语言相比于随意,所以javascript代码中充斥各种奇葩之写法,有时雾里看花,当然,能明白各型各色的写法也是针对
javascript语言特性还进一步的入木三分理解,那么他发出几乎种植写法呢?

 ( function(){…} )()

或者

 ( function (){…} () )

第一要明两个知识点

js中函数是引用类型;
函数一般执行方式:函数名+();

 下面的事例帮您掌握引用类型

var a = function(x,y){
    console.log(x + y);
};
var  b = a;
a(1,2);
b(1,2); //b,a指向同一个函数对象

//b重新赋值
b = function(x,y){
    console.log(x - y);
}
a(1,2);
b(1,2); 

 

函数的几乎种植概念方式

js函数有普普通通函数、构造函数、匿名函数,定义方式产生三种植,即函数声明方式(function
declaration, abbreviation as FD)、函数表达式方式(function expression,
abbreviation as
FE)、函数对象方式(对象的计定义函数,前面参数为函数的参数,最后为函数体。但是急需分析传入的字符串参数,导致个别差解析,所以无推荐这种措施来定义函数)

1、函数声明方式

//不会报错,但是javascript引擎只解析函数声明,忽略后面的括号,函数声明不会被调用
function fnName(){
    alert('Hello World');
}();
//可以执行
alert(sum(1,2)); 
function sum(x,y){
    return x + y; 
}

 2、函数表达式方法

//这段代码会报错
alert(sum(1,2));
var sum = function (x,y){
   return x + y;
}
//函数表达式后面加括号,当javascript引擎解析到此处时能立即调用函数
var show=function(){
    alert('Hello World');
}();

 3、函数对象方法

var sum = new Function('value1', 'value2', 'return value1 + value2');

 在描绘递归的下可以如此勾画

//如果直接用sum(x-1) + sum(x-2),如果sum被改名,或者重新赋值,产生bug
var sum = function fSum(x){
    if(x<=2)
        return 1;
    else
        return fSum(x-1) + fSum(x-2);
};
alert(sum(5));

 4、匿名函数

采取function关键字声明一个函数,但无让函数命名,所以让匿名函数,匿名函数属于函数表达式,匿名函数有那么些意,赋予一个变量则创造函数,赋予一个事件则变成事件处理程序要创造闭包等等

function () {}

区别

1、FD是于构建函数的Execution Context时会见受算并视作Activation
Object的一个性质让引述,因此即便涌出declaration
hoisting的场面。而FE则是以函数的Runtime中才吃算,而且无会见作Activation
Object的一个特性让引述,也就是说FD会被解析器通过函数声明提升的长河尽管function
declaration
hoisting置于原代码数的顶部,所以即使以函数前调用该函数也可以正常下

2、而函数表达式方式除了不能够在宣称前调用外,与函数声明方式同样

3、函数对象方法可以直观地领略“函数是目标,函数名叫是指针”这个概念,但是她见面招致解析器两次于解析,一坏是寻常的ECMAScript代码,一次是分析传入
Function构造函数里的字符串,会潜移默化js引擎性能

4、函数表达式后面可以加括号就调用该函数,函数声明不可以

马上施行函数表达式

俺们以使用JavaScript的时段常常会面看见接近如下的函数调用方式

(function(){ 
    console.log("test");
})();

  或者

(function(){ 
    console.log("test");
}());

 比如jQuery

(function( window, undefined ) {
    // code here
}) ( window );

 这种写法有零星种名叫

「自执行匿名函数」(self-executing anonymous function),
「立即执行函数表达式」(Immediately-Invoked Function Expression,以下简称IIFE)

 还有局部奇葩的概念方式

// 如果本身就是expression,那么根本不需要做任何处理
var i = function(){ return 10; }();
true && function(){ /* code */ }();
0, function(){ /* code */ }();

// 如果你不在乎返回值,可以这么做
!function(){ /* code */ }();
~function(){ /* code */ }();
-function(){ /* code */ }();
+function(){ /* code */ }();

// 还有更奇葩的方式,但是不知道性能如何,来自

new function(){ /* code */ }
new function(){ /* code */ }()

 

胡要为此这实施函数表达式

1、模拟块作用域

引人注目,JavaScript没有C或Java中之块作用域(block),只有函数作用域,在同时调用多个仓库的状下,很易导致对象要变量的幂,比如

liba.js

var num = 1;
// code....

 libb.js

var num = 2;
// code....

 如果以页面被而援引liba.jsliba.js区区只仓库,必然导致num变量被遮盖,为了化解之题目,可以通过IIFE来缓解:

liba.js

(function(){
    var num = 1;
    // code....
})();

 libb.js

(function(){
    var num = 2;
    // code....
})();

2、解决闭包冲突

闭包(closure)是JavaScript的一个言语特色,简单的话即使是在函数内部所定义之函数可以拥有外层函数的实施环境,即使在他层函数已经施行了的状态下,在这里就未详细介绍了,感兴趣的得自动Google。我们这里仅仅选一个是因为闭包引起的无限常见的题目

var f1 = function() {
    var res = [];
    var fun = null;
    for(var i = 0; i < 10; i++) {
        fun = function() { console.log(i);};//产生闭包
        res.push(fun);
    }

    return res;
}

// 会输出10个10,而不是预期的0 1 2 3 4 5 6 7 8 9
var res = f1();
for(var i = 0; i < res.length; i++) {
    res[i]();
}

 修改成:

var f1 = function() {
    var res = [];
    for(var i = 0; i < 10; i++) {
        // 添加一个IIFE
        (function(index) {
            fun = function() {console.log(index);};
            res.push(fun);
        })(i);
    }

    return res;
}

// 输出结果为0 1 2 3 4 5 6 7 8 9
var res = f1();
for(var i = 0; i < res.length; i++) {
    res[i]();
}

 可以参考http://segmentfault.com/q/1010000003490094

3、模拟单例

以JavaScript的OOP中,我们可通过IIFE来实现,如下

var counter = (function(){
    var i = 0; 
    return {
        get: function(){
            return i;
        },
        set: function( val ){
            i = val;
        },
        increment: function() {
            return ++i;
        }
    };
}());

counter.get(); // 0
counter.set( 3 );
counter.increment(); // 4
counter.increment(); // 5

 

参考:
http://benalman.com/news/2010/11/immediately-invoked-function-expression/#iife
http://blog.coolaj86.com/articles/how-and-why-auto-executing-function.html
http://stackoverflow.com/questions/592396/what-is-the-purpose-of-a-self-executing-function-in-javascript
http://www.cnblogs.com/TomXu/archive/2011/12/31/2289423.html
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function