摘要:貼一句書中的原文就是說在代碼中很簡單,沒有任何修飾的調(diào)用,就可以理解為全局的作用域?qū)ο蟆_@種鏈?zhǔn)劫x值,指向問題在中叫做。在這種傳一個(gè)參數(shù)作為對(duì)象的功能方面,與是等價(jià)的。看了以上文章對(duì)于解決面試題應(yīng)該會(huì)有不小的幫助。
書讀到"this & object prototype"這一卷。 章節(jié)到了“this All Makes Sense Now!”
書里面開篇就提到,this并不復(fù)雜,只不過被很多程序員加了自己的臆想以訛傳訛,說到底,還是基礎(chǔ)知識(shí)不熟悉。
的確,看過很多技術(shù)文章,分析this都有那種管中窺豹的感覺就是著重在舉例,論述這個(gè)現(xiàn)象,而不求甚解。
閑言少敘,開始總結(jié)。
首先說一個(gè)重要的技術(shù)名詞,call-site,我們平時(shí)在debug的時(shí)候,可能會(huì)接觸到callstack這個(gè)詞,感覺上其實(shí)有那么一點(diǎn)類似。
我理解:
call-stack:是一連串的方法執(zhí)行的鏈?zhǔn)浇Y(jié)果
call-site:只是上一個(gè)調(diào)用當(dāng)前方法上下文環(huán)境,可以理解為context。
比如下面這個(gè)片段:
function callfirst(){ // call-stack:callfirst // call-site:全局 callsecond(); } function callsecond(){ // call-stack:callfirst -> callsecond // call-site:callfirst } callfirst();
為什么說到這個(gè)call-site,確定this對(duì)象其實(shí)就是找到call-site的過程。
說到這里,還要再提一個(gè)細(xì)節(jié),js中的this,不是面向?qū)ο笾袀鹘y(tǒng)的概念,這個(gè)this不是放在function中就是這個(gè)function的context,也不是任何場合都代表了整個(gè)js運(yùn)行環(huán)境中的context,這個(gè)this,你就可以理解為是剛才提到的call-site,必須是有依據(jù)的context。
下面就總結(jié)一下找到call-site的方法,也就是如何正確找到并使用this。(規(guī)則我就直接使用原文的副標(biāo)題)
1.Default Binding:看看如下代碼片段function foo() { console.log( this.a ); } var a = 2; foo();
這里出現(xiàn)this的地方,是foo方法里,我們先確定call-site,顯而易見,foo方法的call-site就是最后一行foo,隸屬于全局對(duì)象,那么這個(gè)this就呼之欲出了,這個(gè)this就代表這個(gè)代碼的作用域,而this.a訪問的也就是var a = 2;這條語句賦值的屬性,所以控制臺(tái)會(huì)打印出一個(gè)2。
貼一句書中的原文:
“called with a plain, un-decorated function reference. ”
就是說在代碼中很簡單,沒有任何修飾的調(diào)用,this就可以理解為全局的作用域?qū)ο蟆?br>但是這種規(guī)則,不適用于strict mode環(huán)境下的js代碼,如果用在strict mode中,以上代碼需要改寫成為
function foo() { console.log( this.a ); } var a = 2; (function(){ "use strict"; foo(); // 2 })();2.Implicit Binding:還是看代碼
function foo() { console.log( this.a ); } var obj = { a: 2, foo: foo }; obj.foo();
這種直譯為隱式綁定的方法,確定call-site的方法就是看是由誰調(diào)用的方法,在上面這個(gè)例子中,再直白以及明顯不過了,obj中有一個(gè)foo屬性,綁定的foo方法,那么此時(shí)foo方法中的call-site就是obj,obj中有一個(gè)屬性是a,所以代碼會(huì)輸出2
變形:
function foo() { console.log( this.a ); } var obj2 = { a: 42, foo: foo }; var obj1 = { a: 2, obj2: obj2 }; obj1.obj2.foo(); // 42
如果遇到這種鏈?zhǔn)降娘L(fēng)格,就本著就近原則,離foo方法最近的obj2就是foo的call-site,方法中this.a的值就是obj2中a的值。
在Implicit Binding的情況下會(huì)有一種叫Implicitly Lost的情況發(fā)生,簡單直白點(diǎn)說就是剛才那種鏈?zhǔn)秸{(diào)用的方式,被隱藏在了各種其他的情況之下,舉例來說明。
function foo() { console.log( this.a ); } var obj = { a: 2, foo: foo }; var bar = obj.foo; var a = "oops, global"; bar();
上面這種情況將obj.foo賦值給了bar, 按照慣性思維,看到obj.foo第一反應(yīng),我覺得this應(yīng)該等價(jià)于obj,然而事實(shí)卻哐哐打臉,
上面代碼的foo的call-site是bar,雖然鏈?zhǔn)綇?fù)制了一大堆給了bar,但實(shí)際上,bar在這個(gè)時(shí)點(diǎn)是等價(jià)于foo的,所以這個(gè)方法的call-site就是bar,那么this.a的值就是全局屬性的a,與obj就不相干了。
與上面情況相同的還有如下幾種變種情況:
function foo() { console.log( this.a ); } function doFoo(fn) { fn(); } var obj = { a: 2, foo: foo }; var a = "oops, global"; doFoo( obj.foo );
刨除一切感官上的理解,最終調(diào)起foo方法的是fn()這句話,fn的值雖然是由obj.foo傳過來的,但其實(shí)這種情況與上面說到的方式完全是等價(jià)的
解析一下,fn()就是foo的call-site,而根據(jù)第一個(gè)default binding原則,fn前面是干凈沒有任何修飾符的,所以foo中的this代表的就是全局對(duì)象。
這里需要強(qiáng)調(diào)的就是,鏈?zhǔn)椒椒o論是賦值還是作為方法的參數(shù),不能被長長的語句迷惑雙眼,照準(zhǔn)call-site是理順?biāo)悸返囊磺蟹ㄩT。
這種鏈?zhǔn)劫x值,this指向問題在js中叫做fall back to default binding。
3.Explicit Binding說到這個(gè)顯示綁定,就得提到兩個(gè)方法,一個(gè)叫做call,另一個(gè)叫apply,在現(xiàn)在這個(gè)時(shí)點(diǎn),我們暫且理解幾個(gè)點(diǎn),這兩個(gè)方法,是所有function對(duì)象都可以調(diào)用的內(nèi)建方法(涉及到prototype),他們的第一個(gè)參數(shù),我們就可以理解為this對(duì)象,這是一種強(qiáng)制把this注入到方法中的一種手段。舉個(gè)例子
function foo() { console.log( this.a ); } var obj = { a: 2 }; foo.call( obj );
還是熟悉的味道,但是我們卻換了配方,我們不直接調(diào)用foo方法,而是使用foo中的call方法,把obj傳到call中作為foo中的this對(duì)象,控制臺(tái)會(huì)為我們輸出一個(gè)2,call可以換成apply。
foo.apply(obj);
在這種傳一個(gè)參數(shù)作為this對(duì)象的功能方面,call與apply是等價(jià)的。
4 new Binding這個(gè)恐怕也是很多使用js的朋友們最容易混淆的地方,new在js中生成的只是一個(gè)function,new過是在一個(gè)function前面搶了一個(gè)new單詞,而這樣表示會(huì)讓function有一些新的變化
大體上有4點(diǎn):
產(chǎn)生一個(gè)新的function對(duì)象
這個(gè)與原型鏈有關(guān),暫且不說
new出來的function對(duì)象調(diào)用的方法是使用的this,就是它本身
除對(duì)象本身改變自己本身以外,每次new出來的對(duì)象都是全新的對(duì)象(這話我再潤色一下)
上例子:
function foo(a) { this.a = a; } var bar = new foo( 2 ); console.log( bar.a );
這個(gè)比之之前的復(fù)雜情況就太淺顯了,望文生義即可。
看了以上文章對(duì)于解決this面試題應(yīng)該會(huì)有不小的幫助。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/82805.html
摘要:設(shè)計(jì)模式與開發(fā)實(shí)踐讀書筆記。發(fā)布訂閱模式又叫觀察者模式,它定義了對(duì)象之間的一種一對(duì)多的依賴關(guān)系。附設(shè)計(jì)模式之發(fā)布訂閱模式觀察者模式數(shù)據(jù)結(jié)構(gòu)和算法系列棧隊(duì)列優(yōu)先隊(duì)列循環(huán)隊(duì)列設(shè)計(jì)模式系列設(shè)計(jì)模式之策略模式 《JavaScript設(shè)計(jì)模式與開發(fā)實(shí)踐》讀書筆記。 發(fā)布-訂閱模式又叫觀察者模式,它定義了對(duì)象之間的一種一對(duì)多的依賴關(guān)系。當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴它的對(duì)象都將得到通知。 例...
摘要:設(shè)計(jì)模式與開發(fā)實(shí)踐讀書筆記。看此文章前,建議先看設(shè)計(jì)模式之發(fā)布訂閱模式觀察者模式在中,已經(jīng)介紹了什么是發(fā)布訂閱模式,同時(shí),也實(shí)現(xiàn)了發(fā)布訂閱模式。 《JavaScript設(shè)計(jì)模式與開發(fā)實(shí)踐》讀書筆記。 看此文章前,建議先看JavaScript設(shè)計(jì)模式之發(fā)布-訂閱模式(觀察者模式)-Part1 在Part1中,已經(jīng)介紹了什么是發(fā)布-訂閱模式,同時(shí),也實(shí)現(xiàn)了發(fā)布-訂閱模式。但是,就Part1...
閱讀 2771·2021-09-24 10:34
閱讀 1875·2021-09-22 10:02
閱讀 2262·2021-09-09 09:33
閱讀 1466·2021-08-13 15:02
閱讀 3277·2020-12-03 17:10
閱讀 1191·2019-08-30 15:44
閱讀 2152·2019-08-30 12:58
閱讀 3236·2019-08-26 13:40