在JavaScript中,函數是一等公民,函數在JavaScript中是一個數據類型,而非像C#或其餘描述性語言那樣僅僅做爲一個模塊來使用。函數有四種調用模式,分別是:函數調用形式、方法調用形式、構造器形式、以及apply形式。這裏全部的調用模式中,最主要的區別在於關鍵字 this 的意義,下面分別介紹這個幾種調用形式。
程序員
本文主要內容:數組
1.分析函數的四種調用形式
2.弄清楚函數中this的意義
3.明確構造函對象的過程
4.學會使用上下文調用函數瀏覽器
1、函數調用形式app
函數調用形式是最多見的形式,也是最好理解的形式。所謂函數形式就是通常聲明函數後直接調用便是。例如:函數
或者:學習
這兩段代碼都會在瀏覽器中彈出一個對話框,顯示字符串中的文字,這個就是函數調用。動畫
能夠發現函數調用很簡單,就是平時學習的同樣,這裏的關鍵是,在函數調用模式中,函數裏的 this 關鍵字指全局對象,若是在瀏覽器中就是 window 對象。例如:this
此時,會彈出對話框,打印出 [object Window]。spa
2、方法調用模式code
函數調用模式很簡單,是最基本的調用方式。可是一樣的是函數,將其賦值給一個對象的成員之後,就不同了。將函數賦值給對象的成員後,那麼這個就不在稱爲函數,而應該叫作方法。例如:
此時,o.fn 則是方法,不是函數了。實際上 fn 的方法體與 func 是如出一轍的,可是這裏有個微妙的不一樣。看下面的代碼:
// 修改函數體
var func = function() {
alert(this);
};
var o = {};
o.fn = func;
// 比較
alert(o.fn === func);
// 調用
func();
o.fn();
這裏的運行結果是,兩個函數是相同的,所以打印結果是 true。可是因爲兩個函數的調用是不同的,func 的調用,打印的是 [object Window],而 o.fn 的打印結果是 [object Object]。
這裏即是函數調用與方法調用的區別,函數調用中,this 專指全局對象 window,而在方法中 this 專指當前對象,即 o.fn 中的 this 指的就是對象o。
3、構造器調用模式
一樣是函數,在單純的函數模式下,this 表示 window;在對象方法模式下,this 指的是當前對象。除了這兩種狀況,JavaScript 中函數還能夠是構造器。將函數做爲構造器來使用的語法就是在函數調用前面加上一個 new 關鍵字。如代碼:
上面的案例首先建立一個構造函數Person,而後使用構造函數建立對象p。這裏使用 new 語法。而後在使用對象調用sayHello()方法,這個使用構造函數建立對象的案例比較簡單。從案例能夠看到,此時 this 指的是對象自己。除了上面簡單的使用之外,函數做爲構造器還有幾個變化,分別爲:
一、全部須要由對象使用的屬性,必須使用 this 引導;
二、函數的 return 語句意義被改寫,若是返回非對象,就返回this。
構造器中的 this
咱們須要分析建立對象的過程,方能知道 this 的意義。以下面代碼:
這裏首先定義了函數 Person,下面分析一下整個執行:
一、程序在執行到這一句的時候,不會執行函數體,所以 JavaScript 的解釋器並不知道這個函數的內容。
二、接下來執行 new 關鍵字,建立對象,解釋器開闢內存,獲得對象的引用,將新對象的引用交給函數。
三、緊接着執行函數,將傳過來的對象引用交給 this。也就是說,在構造方法中,this 就是剛剛被 new 建立出來的對象。
四、而後爲 this 添加成員,也就是爲對象添加成員。
五、最後函數結束,返回 this,將 this 交給左邊的變量。
分析過構造函數的執行之後,能夠獲得,構造函數中的 this 就是當前對象。
構造器中的 return
在構造函數中 return 的意義發生了變化,首先若是在構造函數中,若是返回的是一個對象,那麼就保留原意。若是返回的是非對象,好比數字、布爾和字符串,那麼就返回 this,若是沒有 return 語句,那麼也返回 this,看下面代碼:
執行代碼,這裏打印的結果是」牛亮亮」。由於構造方法中返回的是一個對象,那麼保留 return 的意義,返回內容爲 return 後面的對象,再看下面代碼:
代碼運行結果是,先彈窗打印[object Object],而後打印」趙曉虎」,由於這裏 return 的是一個字符串,屬於基本類型,那麼這裏的 return 語句無效,返回的是 this 對象,所以第一個打印的是[object Object]而第二個不會打印 undefined。
4、apply調用模式
除了上述三種調用模式之外,函數做爲對象還有 apply 方法與 call 方法可使用,這即是第四種調用模式,我稱其爲 apply 模式。
首先介紹 apply 模式,首先這裏 apply 模式既能夠像函數同樣使用,也能夠像方法同樣使用,能夠說是一個靈活的使用方法。首先看看語法:函數名.apply(對象, 參數數組);
這裏看語法比較晦澀,仍是使用案例來講明:
一、新建兩個 js 文件,分別爲」js1.js」與」js2.js」;
二、添加代碼
// js2.js 文件
var func2 = function() {
this.name = "程序員";
};
var o = {};
func2.apply(o);
alert(o.name);
三、分別運行着兩段代碼,能夠發現第一個文件中的 name 屬性已經加載到全局對象 window 中; 而第二個文件中的 name 屬性是在傳入的對象 o 中,即第一個至關於函數調用,第二個至關 於方法調用。
這裏的參數是方法自己所帶的參數,可是須要用數組的形式存儲在,好比代碼:
// 定義方法
var func = function(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
};
// 建立對象
var o = {};
// 給對象添加成員
// apply 模式
var p1 = func.apply(o, ["趙曉虎", 19, "男"]);
// call 模式
var p2 = func.call(o, "趙曉虎", 19, "男");
上面的代碼,apply 模式與 call 模式的結果是同樣的。
實際上,使用 apply 模式和 call 模式,能夠任意的操做控制 this 的意義,在函數 js 的設 計模式中使用普遍。簡單小結一下,js 中的函數調用有四種模式,分別是:函數式、方法式、構造 器式和 apply 式. 而這些模式中,this 的含義分別爲:在函數中 this 是全局對象 window,在方 法中 this 指當前對象,在構造函數中 this 是被建立的對象,在 apply 模式中 this 能夠隨意的指定.。在 apply 模式中若是使用 null,就是函數模式,若是使用對象,就是方法模式。
5、綜合例子
下面經過一個案例結束本篇吧。案例說明:有一個div,id爲dv,鼠標移到上面去高度增大2倍,鼠標離開恢復,下面直接上js代碼: