調用一個函數會暫停當前函數的執行,傳遞控制權和參數給新函數。除了聲明時定義的形式參數,每一個函數還接受兩個附加參數: this 和 arguments。參數 this 的值取決於調用的模式。在JavaScript中一共有4中調用模式: 方法調用模式、函數調用模式、構造器調用模式和 apply 調用模式。數組
當一個函數被保存爲對象的一個屬性時,咱們稱它爲一個方法。當一個方法被調用時,this 被綁定到該對象。若是調用表達式包含一個提取屬性的動做(即包含一個 .點表達式或[subscript]下標表達式),那麼它就是被當作一個方法來調用。app
// 建立 myObject 對象,有一個 value 屬性和一個 increment 方法 // increment 方法接受一個可選的參數。若是參數不是數字,那麼默認使用數字1 var myObject = { value: 0, increment: function (inc){ this.value += typeof inc === 'number' ? inc : 1; } }; myObject.increment(); document.writeln(myObject.value); // 1 myObject.increment(2); document.writeln(myObject.value); // 3
方法可使用 this 訪問本身所屬的對象,因此它能從對象中取值貨對對象進行修改。 this 到對象的綁定發生在調用的時候。函數
當一個函數並不是一個對象的屬性時,它就是被當作一個函數來調用的。this
var sum = add(3,4); // sum 的值爲7
以此模式調用函數時,this 被綁定到全局對象。這是語言設計上的一個錯誤。若正確,那麼當內部函數被調用時,this 應該仍然綁定到外部函數的 this 變量。這樣設計的後果就是方法不能利用內部函數來幫助它工做,由於內部函數的 this 被綁定了錯誤的值,不能共享該方法對對象的訪問權。prototype
解決方案: 若是該方法定義一個便令並給它賦值爲 this,那麼內部函數就能夠經過那個變量訪問到 this。按照約定,把那個變量命名爲 that:設計
// 給 myObject 增長一個 double 方法 myObject.double = function () { var that = this; // 解決方法 var helper = function () { that.value = add(that.value, that.value); }; helper(); // 以函數的形式調用helper }; // 以方法的形式調用 double myObject.double(); document.writeln(myObject.value); // 6
若是使用嚴格模式(strict mode),那麼全局對象沒法使用默認綁定,this 會綁定到undefinedcode
function foo() { "use strict"; console.log(this.a); } var a = 2; foo(); // TypeError: this is undefined
這裏有一個微妙可是很是中亞偶的細節,雖然 this 的綁定規則徹底取決於調用位置,可是只有 foo() 運行在非 strict mode 下時,默認綁定才能綁定到全局對象;嚴格模式下與 foo() 的調用位置無關:對象
function foo() { console.log(this.a); } var a = 2; (function(){ "use strict"; foo(); // 2 })();
若是在一個函數前面帶上 new 來調用,那麼背地裏將會建立一個鏈接到該函數的 prototype 成員的新對象,同時 this 會被綁定到那個新對象上。繼承
首先,咱們來了解一下構造函數。在傳統的面向類的語言中,「構造函數」是類中的一些特殊方法,使用 new 初始化類時會調用類中的構造函數。一般的形式爲:ip
something = new MyClass(..);
JavaScript也有一個 new 操做符,使用方法看起來和那些面向類的語言同樣,但 JavaScript 中的 new 機制實際上和麪向類語言徹底不一樣。
在 JavaScript 中,構造函數只是一些使用 new 操做符時被調用的函數。它們不屬於某個類,也不會實例化一個類。實際上,它們甚至都不能說是一種特殊的函數類型,它們只是被 new 操做符調用的普通函數而已。包括內置對象函數在內的全部函數均可以用 new 來調用,這種函數調用被稱爲構造函數調用。實際上並不存在所謂的構造函數,只有對於函數的構造調用。
使用 new 來調用函數,會自動執行如下操做:
建立(或者說構造)一個全新的對象。
這個新對象會被執行[[原型]]鏈接
這個新對象會綁定到函數調用的 this
若是函數沒有返回其餘對象,那麼 new 表達式中的函數會自動返回這個新對象
// 建立一個名爲 Quo 構造器函數。它構造一個帶有 status 屬性的對象 var Quo = function (string) { this.status = string; }; // 給 Quo 的全部實例提供一個名爲 get_status 的公共方法 Quo.prototype.get_status = function () { return this.status; }; // 構造一個 Quo 實例 var myQuo = new Quo("confused"); document.writeln(myQuo.get_status()); // confused
apply 方法讓咱們構建一個參數數組傳遞給調用函數,也容許咱們選擇 this 的值。apply 方法接收兩個參數,第一個是要綁定給 this 的值,第二個就是一個參數數組。
// 構造一個包含兩個數字的數組,並將它們相加 var array = [3,4]; var sum = add.apply(null,array); // 7 // 構造一個包含 status 成員的對象 var statusObject = { status: 'A-OK'; }; // statusObject 並無繼承自 Quo.prototype,但咱們能夠在 statusObject 上調用 get_statuse 方法,儘管statusObject 並無一個名爲 get_status 的方法 var status = Quo.prototype.get_status.apply(statusObject); // A-OK