摘要:綁定使用方式進行調用函數時,會發生構造函數的調用。先上圖,然后根據文字閱讀使用調用函數之后,該函數才作為構造函數進行調用,構造一個全新的對象賦值給,而對象的指向了的對象,的對象有一個屬性指向的構造函數這個就是的原型鏈,也是的特性。
javascript語言是在運行時前即進行編譯的,而this的綁定也是在運行時進行綁定的。也就是說,this實際上是在函數被調用時候發生綁定的,它指向什么完全取決于函數在哪里被調用。
1.默認綁定
例如直接在全局作用域下聲明:
var a=2; console.log(this.a);
在全局作用域下聲明的變量或者函數等,都會作為window對象的屬性。
這個時候,默認this是綁定到全局作用域下的window對象,如果你去console.log(this);你會發現,你打印出來的是window,盡管你沒有聲明this就是window,但是js進行了默認綁定。
以至于你運行以下的代碼片段:
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();
兩次會打印出來什么呢?猜一下?
foo()會打印出來4,obj.foo()會打印出來2
第一個foo() 使用了默認綁定,this綁定到了全局對象window,打印 this.a 就是打印window.a;
第二個foo()外層的foo函數引用作為obj.foo的屬性值,通過obj進行調用,此時的obj就是這個函數引用的上下文對象,this會隱式綁定到obj這個對象上。此時打印的this.a就是obj.a了。
3.顯式綁定
在上面兩種綁定中,我們都沒有去明確地進行強制綁定,而是使用了默認規則的綁定,那么如果我們想要在調用某個函數時特定地改變this的綁定,這個時候就可以用顯式綁定了。
還是上代碼,然后進行分析。
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 使用了默認綁定,foo函數的this綁定到了window。
第二次打印了2 使用了call函數,顯式地將foo函數的this綁定到obj對象。
第三次打印了2 apply方法的效果跟call方法一樣。
第四次打印了4 call方法顯示地將foo函數的this綁定到了obj對象,效果跟默認綁定一樣了。
第五次打印了2,bind方法顯示地將foo函數的this綁定到了obj,并且返回了一個硬編碼后的新函數,賦值給foo1變量進行調用,硬編碼就是新函數內部this直接綁定到了指定的對象,也就是obj。
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
foo函數只是一個普通的函數,直接調用foo(3)只是作為普通函數的調用,會使用默認綁定將this綁定到window上,對window.a也就會全局變量a進行賦值,所以打印出來的是3;
foo函數,進行構造調用,this綁定到test對象,故而this.a作為test對象的屬性并進行傳參賦值。打印出來的test就是{a:2},this.a就是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綁定的情況有了基本的了解,才能在編寫代碼時候,避免產生由于綁定帶來的未知bug。如果你在調用某個框架插件或者綁定事件的時候,發現this不好用了,有可能是你的this使用綁定錯了,打印下console.log(this)在控制臺看一看,也許就發現問題了。如果在閱讀中遇到什么問題,歡迎評論以及留言。同時歡迎我的博客陳建光的博客
歡迎評論以及留言,同時歡迎關注我的博客定時不斷地更新我的文章 陳建光的博客
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94221.html
摘要:事件簡介事件是合成事件,所有事件都自動綁定到最外層上。支持事件的冒泡機制,我們可以使用和來中斷它。這樣做簡化了事件處理和回收機制,效率也有很大提升。事件類型合成事件的事件類型是原生事件類型的一個子集。 React事件簡介 React事件是合成事件,所有事件都自動綁定到最外層上。因為Virtual DOM 在內存中是以對象的形式存在的,所以React 基于 Virtual DOM 實現了...
摘要:事件簡介事件是合成事件,所有事件都自動綁定到最外層上。支持事件的冒泡機制,我們可以使用和來中斷它。這樣做簡化了事件處理和回收機制,效率也有很大提升。事件類型合成事件的事件類型是原生事件類型的一個子集。 React事件簡介 React事件是合成事件,所有事件都自動綁定到最外層上。因為Virtual DOM 在內存中是以對象的形式存在的,所以React 基于 Virtual DOM 實現了...
摘要:回調函數中調用在回調函數中一般有兩種情況回調函數為匿名函數時,回調函數的會指向,需要對回調函數?;卣{函數為箭頭函數時,回調函數的會指向他的直接上層。 淺談-this this簡單而又神秘,使用場景多變而又復雜,這造就了它成為了初級javascript開發人員不愿接觸的東西,高級javascript都想探究的東西。文本亦是對this的致敬。 this是什么? this是當前執行環境...
摘要:如果該參數的值為或,則表示不需要傳入任何參數,從開始可以使用類數組對象。當使用操作符調用綁定函數時,該參數無效。當綁定函數被調用時,這些參數將置于實參之前傳遞給被綁定的方法。 在了解call,apply之前需要先了解下javascrit中this指向 this的指向在ES5里面,this永遠指向最后調用它的那個對象舉個栗子: var name = outerName; function...
摘要:將作用域賦值給變量這里的作用域是,而不是將作用域賦值給一個變量閉包返回瀏覽器中內存泄漏問題大家都知道,閉包會使變量駐留在內存中,這也就導致了內存泄漏。 上一章我們講了匿名函數和閉包,這次我們來談談閉包中作用域this的問題。 大家都知道,this對象是在運行時基于函數的執行環境綁定的,如果this在全局就是[object window],如果在對象內部就是指向這個對象,而閉包卻是在運行...
閱讀 4122·2022-09-16 13:49
閱讀 1398·2021-11-22 15:12
閱讀 1519·2021-09-09 09:33
閱讀 1039·2019-08-30 13:15
閱讀 1720·2019-08-29 15:30
閱讀 654·2019-08-27 10:52
閱讀 2643·2019-08-26 17:41
閱讀 1896·2019-08-26 12:11