摘要:綁定使用方式進(jìn)行調(diào)用函數(shù)時(shí),會(huì)發(fā)生構(gòu)造函數(shù)的調(diào)用。先上圖,然后根據(jù)文字閱讀使用調(diào)用函數(shù)之后,該函數(shù)才作為構(gòu)造函數(shù)進(jìn)行調(diào)用,構(gòu)造一個(gè)全新的對(duì)象賦值給,而對(duì)象的指向了的對(duì)象,的對(duì)象有一個(gè)屬性指向的構(gòu)造函數(shù)這個(gè)就是的原型鏈,也是的特性。
javascript語(yǔ)言是在運(yùn)行時(shí)前即進(jìn)行編譯的,而this的綁定也是在運(yùn)行時(shí)進(jìn)行綁定的。也就是說(shuō),this實(shí)際上是在函數(shù)被調(diào)用時(shí)候發(fā)生綁定的,它指向什么完全取決于函數(shù)在哪里被調(diào)用。
1.默認(rèn)綁定
例如直接在全局作用域下聲明:
var a=2; console.log(this.a);
在全局作用域下聲明的變量或者函數(shù)等,都會(huì)作為window對(duì)象的屬性。
這個(gè)時(shí)候,默認(rèn)this是綁定到全局作用域下的window對(duì)象,如果你去console.log(this);你會(huì)發(fā)現(xiàn),你打印出來(lái)的是window,盡管你沒(méi)有聲明this就是window,但是js進(jìn)行了默認(rèn)綁定。
以至于你運(yùn)行以下的代碼片段:
function foo(){ console.log(this.a); } var a=2; foo();
瀏覽器控制臺(tái)打印出來(lái)的是 2 ;
2.隱式綁定
當(dāng)函數(shù)引用有上下文對(duì)象時(shí),在函數(shù)調(diào)用時(shí),會(huì)進(jìn)行隱式綁定。這么說(shuō)肯定很抽象,還是舉例說(shuō)明吧。
var a=4; function foo(){ console.log(this.a); } var obj={ a:2, foo:foo } foo(); obj.foo();
兩次會(huì)打印出來(lái)什么呢?猜一下?
foo()會(huì)打印出來(lái)4,obj.foo()會(huì)打印出來(lái)2
第一個(gè)foo() 使用了默認(rèn)綁定,this綁定到了全局對(duì)象window,打印 this.a 就是打印window.a;
第二個(gè)foo()外層的foo函數(shù)引用作為obj.foo的屬性值,通過(guò)obj進(jìn)行調(diào)用,此時(shí)的obj就是這個(gè)函數(shù)引用的上下文對(duì)象,this會(huì)隱式綁定到obj這個(gè)對(duì)象上。此時(shí)打印的this.a就是obj.a了。
3.顯式綁定
在上面兩種綁定中,我們都沒(méi)有去明確地進(jìn)行強(qiáng)制綁定,而是使用了默認(rèn)規(guī)則的綁定,那么如果我們想要在調(diào)用某個(gè)函數(shù)時(shí)特定地改變this的綁定,這個(gè)時(shí)候就可以用顯式綁定了。
還是上代碼,然后進(jìn)行分析。
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 使用了默認(rèn)綁定,foo函數(shù)的this綁定到了window。
第二次打印了2 使用了call函數(shù),顯式地將foo函數(shù)的this綁定到obj對(duì)象。
第三次打印了2 apply方法的效果跟call方法一樣。
第四次打印了4 call方法顯示地將foo函數(shù)的this綁定到了obj對(duì)象,效果跟默認(rèn)綁定一樣了。
第五次打印了2,bind方法顯示地將foo函數(shù)的this綁定到了obj,并且返回了一個(gè)硬編碼后的新函數(shù),賦值給foo1變量進(jìn)行調(diào)用,硬編碼就是新函數(shù)內(nèi)部this直接綁定到了指定的對(duì)象,也就是obj。
4.new 綁定
使用new方式進(jìn)行調(diào)用函數(shù)時(shí),會(huì)發(fā)生構(gòu)造函數(shù)的調(diào)用。怎么解釋呢,還是直接上代碼加分析。
function foo(a){ this.a=a; } foo(3); var test=new foo(2); console.log(a); console.log(test.a);
打印出來(lái)的是 3 ,2
foo函數(shù)只是一個(gè)普通的函數(shù),直接調(diào)用foo(3)只是作為普通函數(shù)的調(diào)用,會(huì)使用默認(rèn)綁定將this綁定到window上,對(duì)window.a也就會(huì)全局變量a進(jìn)行賦值,所以打印出來(lái)的是3;
foo函數(shù),進(jìn)行構(gòu)造調(diào)用,this綁定到test對(duì)象,故而this.a作為test對(duì)象的屬性并進(jìn)行傳參賦值。打印出來(lái)的test就是{a:2},this.a就是2了。
先上圖,然后根據(jù)文字閱讀
使用new 調(diào)用函數(shù)之后,該foo函數(shù)才作為構(gòu)造函數(shù)進(jìn)行調(diào)用,構(gòu)造一個(gè)全新的對(duì)象賦值給test,而test對(duì)象的_proto_
指向了test的prototype對(duì)象,test的prototype對(duì)象有一個(gè)屬性constructor,指向test的構(gòu)造函數(shù)foo,這個(gè)就是javascript的原型鏈,也是javascript的特性。對(duì)于test對(duì)象調(diào)用的方法以及屬性,會(huì)先在test對(duì)象進(jìn)行尋找,如果找到的話(huà),就直接進(jìn)行調(diào)用,尋找停止。如果尋找不到,順著原型鏈,在test對(duì)象的prototype對(duì)象尋找,如果找到的話(huà),進(jìn)行調(diào)用,尋找停止,如果還是找不到,會(huì)在prototype對(duì)象的原型上進(jìn)行尋找,這個(gè)時(shí)候_proto_指向了Object的prototype對(duì)象,Object的prototype的constructor指向了Object()本身,而一些Obejct的函數(shù)如toString等等就是在這個(gè)原型上進(jìn)行調(diào)用的,這個(gè)時(shí)候如果還是找不到需要屬性或者方法,那么就是語(yǔ)法錯(cuò)誤,未定義了。因?yàn)镺bject的prototype的_proto_指向是null了,也就沒(méi)有任何對(duì)象屬性以及方法了。不是說(shuō)程序員可以new 很多個(gè)對(duì)象嘛,但是new出來(lái)的對(duì)象 原型最終結(jié)果卻是指向了 空(null),所以還是自己動(dòng)手豐衣足食吧,哈哈。
一般情況下,使用new函數(shù)之后構(gòu)造的對(duì)象,會(huì)優(yōu)先將函數(shù)調(diào)用到的this綁定到這個(gè)對(duì)象,如果函數(shù)沒(méi)有返回其它對(duì)象,會(huì)自動(dòng)調(diào)用返回這個(gè)新對(duì)象。
總結(jié):
只有對(duì)于this綁定的情況有了基本的了解,才能在編寫(xiě)代碼時(shí)候,避免產(chǎn)生由于綁定帶來(lái)的未知bug。如果你在調(diào)用某個(gè)框架插件或者綁定事件的時(shí)候,發(fā)現(xiàn)this不好用了,有可能是你的this使用綁定錯(cuò)了,打印下console.log(this)在控制臺(tái)看一看,也許就發(fā)現(xiàn)問(wèn)題了。如果在閱讀中遇到什么問(wèn)題,歡迎評(píng)論以及留言。同時(shí)歡迎我的博客陳建光的博客
歡迎評(píng)論以及留言,同時(shí)歡迎關(guān)注我的博客定時(shí)不斷地更新我的文章 陳建光的博客
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/94221.html
摘要:事件簡(jiǎn)介事件是合成事件,所有事件都自動(dòng)綁定到最外層上。支持事件的冒泡機(jī)制,我們可以使用和來(lái)中斷它。這樣做簡(jiǎn)化了事件處理和回收機(jī)制,效率也有很大提升。事件類(lèi)型合成事件的事件類(lèi)型是原生事件類(lèi)型的一個(gè)子集。 React事件簡(jiǎn)介 React事件是合成事件,所有事件都自動(dòng)綁定到最外層上。因?yàn)閂irtual DOM 在內(nèi)存中是以對(duì)象的形式存在的,所以React 基于 Virtual DOM 實(shí)現(xiàn)了...
摘要:事件簡(jiǎn)介事件是合成事件,所有事件都自動(dòng)綁定到最外層上。支持事件的冒泡機(jī)制,我們可以使用和來(lái)中斷它。這樣做簡(jiǎn)化了事件處理和回收機(jī)制,效率也有很大提升。事件類(lèi)型合成事件的事件類(lèi)型是原生事件類(lèi)型的一個(gè)子集。 React事件簡(jiǎn)介 React事件是合成事件,所有事件都自動(dòng)綁定到最外層上。因?yàn)閂irtual DOM 在內(nèi)存中是以對(duì)象的形式存在的,所以React 基于 Virtual DOM 實(shí)現(xiàn)了...
摘要:回調(diào)函數(shù)中調(diào)用在回調(diào)函數(shù)中一般有兩種情況回調(diào)函數(shù)為匿名函數(shù)時(shí),回調(diào)函數(shù)的會(huì)指向,需要對(duì)回調(diào)函數(shù)。回調(diào)函數(shù)為箭頭函數(shù)時(shí),回調(diào)函數(shù)的會(huì)指向他的直接上層。 淺談-this this簡(jiǎn)單而又神秘,使用場(chǎng)景多變而又復(fù)雜,這造就了它成為了初級(jí)javascript開(kāi)發(fā)人員不愿接觸的東西,高級(jí)javascript都想探究的東西。文本亦是對(duì)this的致敬。 this是什么? this是當(dāng)前執(zhí)行環(huán)境...
摘要:如果該參數(shù)的值為或,則表示不需要傳入任何參數(shù),從開(kāi)始可以使用類(lèi)數(shù)組對(duì)象。當(dāng)使用操作符調(diào)用綁定函數(shù)時(shí),該參數(shù)無(wú)效。當(dāng)綁定函數(shù)被調(diào)用時(shí),這些參數(shù)將置于實(shí)參之前傳遞給被綁定的方法。 在了解call,apply之前需要先了解下javascrit中this指向 this的指向在ES5里面,this永遠(yuǎn)指向最后調(diào)用它的那個(gè)對(duì)象舉個(gè)栗子: var name = outerName; function...
摘要:將作用域賦值給變量這里的作用域是,而不是將作用域賦值給一個(gè)變量閉包返回瀏覽器中內(nèi)存泄漏問(wèn)題大家都知道,閉包會(huì)使變量駐留在內(nèi)存中,這也就導(dǎo)致了內(nèi)存泄漏。 上一章我們講了匿名函數(shù)和閉包,這次我們來(lái)談?wù)勯]包中作用域this的問(wèn)題。 大家都知道,this對(duì)象是在運(yùn)行時(shí)基于函數(shù)的執(zhí)行環(huán)境綁定的,如果this在全局就是[object window],如果在對(duì)象內(nèi)部就是指向這個(gè)對(duì)象,而閉包卻是在運(yùn)行...
閱讀 4188·2022-09-16 13:49
閱讀 1412·2021-11-22 15:12
閱讀 1536·2021-09-09 09:33
閱讀 1050·2019-08-30 13:15
閱讀 1739·2019-08-29 15:30
閱讀 674·2019-08-27 10:52
閱讀 2652·2019-08-26 17:41
閱讀 1908·2019-08-26 12:11