小菊花課堂之JavaScript關於this

關於this

上一章咱們講了關於做用域和閉包的相關知識,如今開始新一輪的學習,那就是JavaScript中最複雜的機制之一---this關鍵字。它是一個很特別的關鍵字,被自動定義在全部函數的做用域中。另外咱們須要明確的一點就是,this在任何狀況下都不指向函數的詞法做用域。數組

那麼咱們來看看this究竟是怎麼樣的機制。this是在運行時進行綁定的,它的上下文取決於函數調用時的各類條件。另外,this的綁定和函數聲明的位置沒有任何關係,之取決於函數的調用方式。閉包

this的四條綁定規則

默認綁定

默認綁定就是最經常使用的獨立函數調用時所綁定的。思考一下代碼app

function foo() {
    console.log(this.a);
}
var a = 2;
foo(); // 2

咱們能夠看到,當調用foo()時,this.a被解析成了全局變量a。
可是,若是使用嚴格模式,那麼就不能將全局對象用於默認綁定,報錯TypeError:this is undefined函數

隱式綁定

一個對那個內部包含一個指向函數的屬性,並經過這個屬性間接引用函數,從而把this隱式綁定到這個對象上。因此這一條就須要考慮調用位置是否有上下文對象。學習

function foo() {
    console.log(this.a);
}
var obj = {
    a : 2,
    foo: foo
};
obj.foo(); // 2

這段代碼中,當foo()被調用時,前面加上了對obj的引用。當函數引用有上下文對象時,隱式綁定規則會把函數調用中的this綁定到這個上下文對象。另外,對象屬性引用鏈中只有上一層或者說最後一層在調用位置中起做用。也就是說,this永遠都是指向最近調用的位置。this

顯式綁定

前面說了隱式綁定的概念,那麼咱們若是不想在對象內部包含函數引用,而想在某個對象上強制調用函數,該如何作呢?
JavaScript中提供了兩個方法,分別是call()apply(),那麼咱們應該怎麼在實際中運用呢?
首先咱們要搞清楚call()apply()的做用,這裏引用MDN上的解釋:prototype

call() 方法調用一個函數, 其具備一個指定的this值和分別地提供的參數(參數的列表)。
apply() 方法調用一個具備給定this值的函數,以及做爲一個數組(或相似數組對象)提供的參數。
具體如何實現,這裏不做展開說明,能夠自行研究,加深理解。code

能夠看出,它們倆的差別僅在於所需參數的形式不一樣,ok迴歸正題。
請看下面代碼:對象

function foo() {
    console.log(a);
}
var obj = {
    a: 2
}
foo.call(obj); // 2

這樣,咱們就能夠在調用foo的時候強制把它的this綁定到obj上ip

new綁定

在傳統的面向類語言中,使用new初始化類時會調用類中的構造函數。可是,JavaScript中的構造函數只是使用new操做符時被調用的函數。它們並不屬於某個類,也不會實例化一個類。
JavaScript中使用new調用函數時,會自動執行下面操做

  1. 構造一個新對象
  2. 新對象會被執行[[prototype]]鏈接
  3. 新對象會綁定函數調用的this
  4. 若是函數沒有返回其餘對象,那麼new表達式中的函數調用會自動返回這個新對象

判斷this

那麼咱們在判斷函數在某個調用位置應該應用哪條規則呢,優先級如何判斷呢?有下面四條法寶供參考

  1. 函數是否在new中調用?若是是,則this綁定的是新對象
    var bar = new foo()
  2. 函數是否經過call、apply調用?若是是,則this綁定的是指定對象
    var bar = foo.call(obj)
  3. 函數是否在某個上下文對象中調用?若是是,則this綁定的是上下文對象
    var bar = obj.foo()
  4. 若是都不是的話,使用默認綁定。注意,在嚴格模式下,就綁定到undefined,不然就綁定到全局對象
    var bar = foo()

固然,也許會有例外的狀況發生,暫時先留着,你們一塊兒思考一下,看看會在什麼狀況下出現這種例外狀況。

那麼,今天就先到這裏啦
see u ~ again

相關文章
相關標籤/搜索