JavaScript函数的有余定义方法

缘起

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)、函数对象格局(对象的主意定义函数,前边参数为函数的参数,最终为函数体。不过需求分析传入的字符串参数,导致一遍解析,所以不推荐那种办法来定义函数)

一 、函数表明格局

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

 贰 、函数表明式方法

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

 三 、函数对象方法

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));

 ④ 、匿名函数

采用function关键字声喜宝(Dumex)个函数,但未给函数命名,所以叫匿名函数,匿名函数属于函数表明式,匿名函数有很多功力,赋予壹个变量则开创函数,赋予贰个轩然大波则改为事件处理程序或创设闭包等等

function () {}

区别

① 、FD是在创设函数的Execution Context时会被计算并作为Activation
Object的二个属性被引述,因而就出现declaration
hoisting的景观。而FE则是在函数的Runtime中才被总括,而且不会作为Activation
Object的三个属性被引用,也等于说FD会被解析器通过函数表明提高的长河即function
declaration
hoisting置于原代码数的顶部,所以尽管在函数前调用该函数也可以符合规律使用

贰 、而函数表达式格局除了不只怕在申明前调用外,与函数申明方式同样

叁 、函数对象方法可以直观地知道“函数是目的,函数名是指针”这一个定义,不过它会促成解析器一遍解析,两次是普普通通的ECMAScript代码,三次是分析传入
Function构造函数里的字符串,会潜移默化js引擎质量

四 、函数表明式前面能够加括号随即调用该函数,函数注明不能够

霎时实施函数表达式

笔者们在动用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 */ }()

 

缘何要用马上实施函数表明式

壹 、模拟块效率域

眼看,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....
})();

二 、消除闭包抵触

闭包(closure)是JavaScript的三个语言特色,简单的说就是在函数内部所定义的函数可以有所外层函数的进行环境,固然在外层函数已经履行完结的场地下,在那边就不详细介绍了,感兴趣的可以活动谷歌。我们那边只举一个由闭包引起的最广泛的题材

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

叁 、模拟单例

在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