在JavaScript語言中存在一個this
關鍵詞,這個關鍵詞指的是函數運行時所在的環境。因爲函數能夠在不一樣的運行環境執行,因此須要有一種機制,可以在函數體內部得到當前的運行環境(context)。因此,this
就出現了,它的設計目的就是在函數體內部,指代函數當前的運行環境。bash
前一個系列的做用域講過,做用域運用的是詞法做用域,意味着是編寫時肯定的,但this與其工做原理徹底不一樣,它的指向並非編寫時肯定的,而是運行時肯定。markdown
以前在閱讀 You Don't Know JS系列的: this & Object Prototypes中,將this的指向總結了幾條規則:數據結構
函數調用方式與內部
this
指針關係:app
this
指向全局對象window
this
指向觸發事件的對象call
的方法來間接調用方法:函數內部this指向call
方法的第一參數對象,咱們能夠建立結構相同,但內容不一樣的對象new
的方式來調用:函數內部this
指向本次函數執行時對應的一個匿名對象(以new的方式建立的函數,函數名的首字母通常以大寫字母開始)new
關鍵詞調用,經過apply
、call
方法不會改變內部的this
指向參考了上面的規則發現,this
的指向不管如何都逃脫不了上面的5大原則,那它們以前是否存在必定的規律呢,或者說是什麼來決定this
的指向的。函數
一般咱們會對一下例子的結果無法準確的肯定this
指向:oop
var name = 'zhou'; var obj = { name: 'shaw', say: function () { console.log(this.name); } } obj.say(); var say = obj.say; say(); 複製代碼
上面的輸出結果會是什麼呢:this
obj.say(); // 輸出shaw
say(); // 輸出zhou
複製代碼
爲何這裏obj.say
和say
的輸出結果會不一致呢?下面咱們來一探究竟。spa
this
的指向與數據在內存裏的數據結構有關:設計
上面案例裏的obj
對象是如何在內存中存儲的呢指針
obj.say-> { [[value]]: say函數地址 [[write]]: true, [[readable]]: true } 複製代碼
實際上say
函數並無存儲在obj
對象中,它只存儲了say
函數的地址。
咱們直接經過obj.say
來調用函數,與obj.say
賦值給say
變量調用徹底不一樣,由於obj
中存儲的是say函數
的地址,咱們進行賦值操做時直接將say函數地址直接賦值過去了,而不是咱們想象的將obj.say
引用賦值過去。