JavaScript學習總結(四)function函數部分


概念

函數是由事件驅動的或者當它被調用時執行的可重複使用的代碼塊。

js 支持兩種函數:一類是語言內部的函數(如eval() ),另外一類是本身建立的。javascript

JavaScript 函數內部聲明的變量(使用 var)是局部變量,因此只能在函數內部訪問它。(該變量的做用域是局部的)。java

您能夠在不一樣的函數中使用名稱相同的局部變量,由於只有聲明過該變量的函數才能識別出該變量。jquery

函數調用

有以下四種調用js函數的方式:編程

  • 做爲函數
  • 做爲方法
  • 做爲構造函數
  • 經過call()apply()

返回函數的函數

1. 當函數無明確返回值時,返回的值就是`undefined`。

2. 當函數有返回值時,返回值是什麼就返回什麼。

咱們能夠經過使用 return 語句實現將函數返回調用它的地方。segmentfault

在使用 return 語句時,函數會中止執行,並返回指定的值。數組

函數一般會返回一個惟一值,那麼這個值也多是另外一個函數:閉包

<script type="text/javascript">
    //函數表達式
    var box = function(){
        var a=1;
        return function(){
            alert(a++)
        }
            alert(a);//永遠不會執行
    }
    alert(box());//彈出"function(){alert(a++)}"
</script>

在這裏,咱們只需將返回值賦值給某個變量,而後就能夠像使用通常函數那樣調用它了:app

<script type="text/javascript">
    var box = function(){
        var a=1;
        return function(){
            alert(++a)
        }
    }
    var newFunc = box();
    newFunc();//2
</script>

若是想讓返回的函數當即執行,亦可使用box()()來執行這段代碼。函數


ECMAScript全部函數的參數都是按值傳遞的,言下之意就是參數不會按引用傳遞。學習

PS:若是存在按引用傳遞的話,那麼函數裏的那個變量將會是全局變量,在外部也能夠訪問。

(1)值類型:數值、布爾值、null、undefined。
(2)引用類型:對象、數組、函數。

引用類型值:指的是那些保存在堆內存中的對象,意思是,變量中保存的實際上只是一個指針,這個指針執行內存中的另外一個位置,由該位置保存對象;

建立匿名函數

function(){
    return ‘hi’;     //單獨的匿名函數是沒法運行的,就算能運行也沒法調用,由於沒有名字
}

這種匿名函數的用法在JQuery中很是多。直接聲明一個匿名函數,當即使用。用匿名函數的好處就是免得定義一個用一次就不用的函數,並且免了命名衝突的問題,js中沒有命名空間的概念,所以很容易函數名字衝突,一旦命名衝突以最後聲明的爲準。

javascript語言裏任何匿名函數都是屬於window對象。在定義匿名函數時候它會返回本身的內存地址,若是此時有個變量接收了這個內存地址,那麼匿名函數就能在程序裏被使用了,由於匿名函數也是在全局執行環境構造時候定義和賦值,因此匿名函數的this指向也是window對象

(function(){
   console.log(this === window);//true
})();

經過自我執行來執行匿名函數:

//經過自我執行來執行匿名函數

<script type="text/javascript">
  (function (){         // (匿名函數)();第一圓括號放匿名函數,第二個圓括號執行
       alert('Lee');
  })();
</script>

把匿名函數自我執行的返回值賦給變量:

//把匿名函數自我執行的返回值賦給變量

<script type="text/javascript">
    var box =  (function (){           
           alert('Lee');
      })();         //彈出」Lee」;
    alert(box);   //彈出 undefined
</script>

var box= (function () {
    return 'hi';
})();
console.log(box);//hi

自我執行匿名函數的傳參:

//自我執行匿名函數的傳參

<script type="text/javascript">
    (function (age){
         alert(age);
    })(100);          //彈出100
</script>

自執行函數的三種寫法

var result = function (){
    alert(2);
}();

另外一種語法也可獲得一樣結果:

var result = (function () {
    console.log(2);
})();

將函數返回值分配給變量:

var result = (function () {
    return 2;
}());

js建立動態函數:

  js支持建立動態函數,動態函數必須用Function對象來定義(Function是js中的一個對象,是固定不變的,規定Function對象的"F"必須大寫,當是function的時候,咱們知道是定義函數的時候所使用的一個關鍵字:function funName(x,y),當是Function的時候(F大寫的時候),咱們知道是js中的對象)

建立動態函數的基本格式:var 變量名 = new Function("參數1","參數2","參數n","執行語句");

看下面的一段代碼:

<script type="text/javascript">
    var square = new Function ("x","y","var sum ; sum = x+y;return sum;");
    alert("square(2,3)的結果是:"+square(2,3));  //square(2,3)的結果是:5
</script>

square是動態建立的函數,在Function對象後面的括號裏的每一部份內容都必須是字符串形式的,也就是說都必須用引號(""或者是'')括起來

這段代碼:

var square = new Function ("x","y","var sum ; sum = x+y;return sum;");

和下面這段代碼:

//函數聲明
    function square (x,y){
          var sum;
          sum = x+y;
          return sum;
     }

是一摸同樣的,只不過一個是動態函數,一個是靜態函數
咱們爲何要把代碼分紅一小段一小段的代碼呢?,把一個字符串分紅了若干個獨立的字符串的優勢就在於咱們能夠經過修改其中的某些字符串來隨時改變函數的做用。

回調函數

回調就是一個函數的調用過程。那麼就從理解這個調用過程開始吧。函數a有一個參數,這個參數是個函數b,當函數a執行完之後執行函數b。那麼這個過程就叫回調。

其實中文也很好理解:回調,回調,就是回頭調用的意思。函數a的事先幹完,回頭再調用函數b。

這裏必須清楚一點:函數b是你以參數形式傳給函數a的,那麼函數b就叫回調函數。

在jquery裏的絕大多數效果函數都涉及到callback函數。jquery效果函數
例如:

<script type="text/javascript">
        $("div").show(1000,function(){
            //callback function
        });
</script>

這裏的callback function換成實例能夠是:

<script type="text/javascript">
    $("div").show(1000,function(){
        console.log("hello world")
    });
</script>

Callback其實是,當一個函數執行完後,現執行的那個函數就是所謂的callback函數。怎麼樣?很好理解吧……

方法和函數的區別

var arr = [1,2,3,4,5]
var a =12;   // 變量:自由的
arr.a= 5;     //屬性:屬於一個對象
function show()     //函數:自由的
{
     alert(‘a’);
}
arr.fn = function()   //方法:屬於一個對象
{
     alert(‘b’);
}

其實方法就是函數,只不過方法是有所屬的對象。

咱們所熟知的,將函數綁定到 click 事件
語法:

$(selector).click(function)
參數 描述
function 可選。規定當發生 click 事件時運行的函數.

這種形式在jquery中常常見到。它是將function當作該方法的參數,向該方法添加一個事件處理函數。

js全局函數

全局函數與內置對象的屬性或方法不是一個概念。全局函數它不屬於任何一個內置對象。
JavaScript 中包含如下 7 個全局函數,用於完成一些經常使用的功能:

escape( )、eval( )、isFinite( )、isNaN( )、parseFloat( )、
parseInt( )、unescape( )。

函數的幾個做用

做爲一個類構造器使用

function Class(){}
Class.prototype={};
var item=new Class();

做爲閉包使用

(function(){
    //獨立做用域
})();

做爲構造函數調用

所謂構造函數,就是經過這個函數生成一個新對象(object)。

<script type="text/javascript"> 
        function Test(){//大寫,以區分普通函數
            this.x = 10;
        }

        var obj = new Test();
        alert(obj.x); //彈出 10;
 </script>

可使用 new 運算符結合像 Object()Date()Function() 這樣的預約義的構造函數來建立對象並對其初始化。面向對象的編程其強有力的特徵是定義自定義構造函數以建立腳本中使用的自定義對象的能力。建立了自定義的構造函數,這樣就能夠建立具備已定義屬性的對象。下面是自定義函數的示例(注意 this 關鍵字的使用)。

function Circle (xPoint, yPoint, radius) {
    this.x = xPoint;  // 圓心的 x 座標。
    this.y = yPoint;  // 圓心的 y 座標。
    this.r = radius;  // 圓的半徑。
}

調用 Circle 構造函數時,給出圓心點的值和圓的半徑(全部這些元素是徹底定義一個獨特的圓對象所必需的)。結束時 Circle 對象包含三個屬性。下面是如何例示 Circle 對象。

var aCircle = new Circle(5, 11, 99);

使用構造器函數的優勢是,它能夠根據參數來構造不一樣的對象。 缺點是構造時每一個實例對象都會生成重複調用對象的方法,形成了內存的浪費。

<script type="text/javascript">
    function Test(name){
        this.occupation = "coder";
        this.name = name;
        this.whoAreYou = function(){
            return "I'm " + this.name + "and I'm a " + this.occupation;
        }
    }
    var obj = new Test('trigkit4');//利用同一個構造器建立不一樣的對象
    var obj2 = new Test('student');
    
    obj.whoAreYou();//"I'm trigkit4 and I'm a corder"
    obj2.whoAreYou();//"I'm student and I'm a corder"     
 </script>

依照慣例,咱們應該將構造器函數的首字母大寫,以便顯著地區別於通常的函數。


如下兩種形式的定義函數方式是等價的。

<script type="text/javascript">
    var test = function(){
        alert("Hello World");
    }
    alert(typeof(test));//output function
</script>

這裏明肯定義了一個變量test,他的初始值被賦予了一個function實體
<br/>

<script type="text/javascript">
    function test(){
        alert("Hello World");
    }
    alert(typeof(test));//output function
</script>

<br/>
看看下面這種定義式函數形式:

<script type="text/javascript">
        function test(){
            alert("Hello World");
        };
        test();//竟然輸出Hello,很奇怪不是嗎?
        
        function test(){
            alert("Hello");
        };
        test();//正常滴輸出了Hello
</script>

很顯然,第一個函數並無起到做用,很奇怪不是嗎?咱們知道,javascript解析引擎並非一行一行地執行代碼,而是一段一段地執行代碼。在同一段程序的分析執行中,定義式的函數語句會被優先執行,因此第一個定義的代碼邏輯已經被第二個覆蓋了,因此兩次調用相同函數,只會執行第二個。

做爲值的函數

函數在js中不只是一種語法,也是一個值。也就是說能夠將函數賦值給變量,存儲在對象的屬性或數組的元素中,做爲參數傳入另外一個函數中。
函數的名字實際是看不見的,它僅僅是變量的名字,這個變量指代函數對象

<script type="text/javascript">
     function square(x,y){
         return x*y;
     }
     var s = square; //s和square指代同一個函數
     square(2,3);//6
     s(2,4);//8
</script>

除了能夠將函數賦值給變量,一樣能夠將函數賦值給對象的屬性,當函數做爲對象的屬性調用時,函數就稱爲方法

<script type="text/javascript">
     var obj = {square:function(x,y){ //對象直接量
         return x*y;
     }};
     var ect = obj.square(2,3);
</script>

prototype屬性

每個函數都包含prototype屬性,這個屬性指向一個對象的引用,這個對象稱爲原型對象。
詳見:javascript學習總結(五)原型和原型鏈

call()和apply()

apply()函數有兩個參數:第一個參數是上下文,第二個參數是參數組成的數組。若是上下文是null,則使用全局對象代替。例如:

function.apply(this,[1,2,3])

call()的第一個參數是上下文,後續是實例傳入的參數序列,例如:

function.call(this,1,2,3);

高階函數

這裏的高階函數可不是高數裏的那個高階函數,所謂高階函數就是操做函數的函數,它接收一個或多個函數做爲參數,並返回新函數

參數arguments

當函數被調用時,會獲得一個免費奉送的參數數組,那就是arguments數組。經過它,函數能夠訪問全部它被調用時傳遞給他的參數列表。這使得編寫一個無需指定參數個數的函數成爲可能。

<script type="text/javascript">
    var sum = function(){
        var i ,sum =0;
        for(i = 0;i<arguments.length;i+=1){
            sum+=arguments[i];
        }
        return sum;
    };
    document.writeln(sum(4,5,23,13,35,46,-10));//116
</script>

ECMAScript中的參數在內部是用一個數組來表示的,函數接收到的始終都是這個數組,而不關心數組中包含哪些參數

function add(num1,num2){
    num = num1 + num2;
    return num;
}

var result = 12,count = 20;
alert(add(result,count));//32;命名的參數只提供便利,解析器不會驗證命名參數

實際上,arguments並非一個真正的數組,它只是一個類數組的對象,它擁有一個length屬性,但他缺乏全部數組的方法。另外,arguments對象的長度是由傳入的參數個數決定的,而不是由定義函數時的命名參數的個數決定的

函數在定義或者聲明的時候,全部的參數都是形參,所以,咱們能夠根據實際狀況來命名參數,函數也只有在被調用時纔會傳入實參。而每一個函數在被調用時都會自動取得兩個特殊變量:thisarguments

函數的遞歸

函數的遞歸,即一個函數在經過名字調用自身的狀況下構成的:

經過使用argument.callee代替函數名:

//arguments.callee是一個指向正在執行的函數的指針
<script>
    function factorial(num){
        if(num<=1){
            return 1;
        }else{
            return num*arguments.callee(num-1);
        }
    }
</script>

思惟導圖

最後附上一張前輩總結的思惟導圖:

請輸入圖片描述

相關文章
相關標籤/搜索