javascript語言是在運行時前即進行編譯的,而this的綁定也是在運行時進行綁定的。也就是說,this其實是在函數被調用時候發生綁定的,它指向什麼徹底取決於函數在哪裏被調用。
1.默認綁定javascript
例如直接在全局做用域下聲明:java
var a=2; console.log(this.a);
以致於你運行如下的代碼片斷:
function foo(){ console.log(this.a); } var a=2; foo();
瀏覽器控制檯打印出來的是 2 ;
2.隱式綁定程序員
當函數引用有上下文對象時,在函數調用時,會進行隱式綁定。這麼說確定很抽象,仍是舉例說明吧。
var a=4; function foo(){ console.log(this.a); } var obj={ a:2, foo:foo } foo(); obj.foo();
兩次會打印出來什麼呢?猜一下?
3.顯式綁定瀏覽器
在上面兩種綁定中,咱們都沒有去明確地進行強制綁定,而是使用了默認規則的綁定,那麼若是咱們想要在調用某個函數時特定地改變this的綁定,這個時候就能夠用顯式綁定了。
仍是上代碼,而後進行分析。app
var a=4; function foo(){ console.log(this.a); } var obj={ a:2, foo:foo } var foo1=foo.bind(obj); foo(); foo.call(obj); foo.apply(obj); foo.call(window); foo1();
按照順序打印出的是 4 ,2 ,2, 4,2
4.new 綁定框架
使用new方式進行調用函數時,會發生構造函數的調用。怎麼解釋呢,仍是直接上代碼加分析。
function foo(a){ this.a=a; } foo(3); var test=new foo(2); console.log(a); console.log(test.a);
打印出來的是 3 ,2
先上圖,而後根據文字閱讀
使用new 調用函數以後,該foo函數才做爲構造函數進行調用,構造一個全新的對象賦值給test,而test對象的_proto_
指向了test的prototype對象,test的prototype對象有一個屬性constructor,指向test的構造函數foo,這個就是javascript的原型鏈,也是javascript的特性。對於test對象調用的方法以及屬性,會先在test對象進行尋找,若是找到的話,就直接進行調用,尋找中止。若是尋找不到,順着原型鏈,在test對象的prototype對象尋找,若是找到的話,進行調用,尋找中止,若是仍是找不到,會在prototype對象的原型上進行尋找,這個時候_proto_指向了Object的prototype對象,Object的prototype的constructor指向了Object()自己,而一些Obejct的函數如toString等等就是在這個原型上進行調用的,這個時候若是仍是找不到須要屬性或者方法,那麼就是語法錯誤,未定義了。由於Object的prototype的_proto_指向是null了,也就沒有任何對象屬性以及方法了。不是說程序員能夠new 不少個對象嘛,可是new出來的對象 原型最終結果倒是指向了 空(null),因此仍是本身動手豐衣足食吧,哈哈。函數
通常狀況下,使用new函數以後構造的對象,會優先將函數調用到的this綁定到這個對象,若是函數沒有返回其它對象,會自動調用返回這個新對象。this
總結:編碼
只有對於this綁定的狀況有了基本的瞭解,才能在編寫代碼時候,避免產生因爲綁定帶來的未知bug。若是你在調用某個框架插件或者綁定事件的時候,發現this很差用了,有多是你的this使用綁定錯了,打印下console.log(this)在控制檯看一看,也許就發現問題了。若是在閱讀中遇到什麼問題,歡迎評論以及留言。同時歡迎個人博客陳建光的博客spa
歡迎評論以及留言,同時歡迎關注個人博客定時不斷地更新個人文章 陳建光的博客