關(guān)于this的二三事

什么是this

this是JS中一個(gè)非常重要的關(guān)鍵字澜公。this 就是你 call 一個(gè)函數(shù)時(shí)尾组,傳入的 context粟矿。任何形式的函數(shù)調(diào)用都可以寫成call形式污尉,傳入的第一個(gè)參數(shù)就是this膀哲。

f(a,b)   等價(jià)于  f.call(undefined , a , b)
f.m.n(a,b)  等價(jià)于  f.m.n.call(f.m , a , b)
fn.call(context , p1 , p2)

所以當(dāng)我們無(wú)法確定this時(shí)我們可以轉(zhuǎn)換成call形式來確認(rèn)this。

如何確定this

通常我們確定this會(huì)用以下方式

1被碗、console.log(this)
2某宪、查看API源代碼
3、查看API相關(guān)文檔

this的使用

全局變量

function f() {
  console.log(this); // window
}
var a=1
function f() {
  console.log(this.a); 
}
f()
//1

對(duì)象的方法

當(dāng)A對(duì)象的方法被賦予B對(duì)象蛮放,該方法中的this就從指向A對(duì)象變成了指向B對(duì)象。所以要特別小心奠宜,將某個(gè)對(duì)象的方法賦值給另一個(gè)對(duì)象包颁,會(huì)改變this的指向。

var obj ={
  foo: function () {
    console.log(this);
  }
};
obj.foo()  // obj

但是压真,只有這一種用法(直接在obj對(duì)象上調(diào)用foo方法)娩嚼,this指向obj;其他用法時(shí)滴肿,this都指向代碼塊當(dāng)前所在對(duì)象(瀏覽器為window對(duì)象)岳悟。

(obj.foo = obj.foo)()
/ 等價(jià)于 /
(obj.foo = function () {
  console.log(this);
})()
//window

可以這樣理解,obj和obj.foo儲(chǔ)存在兩個(gè)內(nèi)存地址泼差,簡(jiǎn)稱為M1和M2贵少。只有obj.foo()這樣調(diào)用時(shí),是從M1調(diào)用M2堆缘,因此this指向obj滔灶。但是,上面情況是直接取出M2進(jìn)行運(yùn)算吼肥,然后就在全局環(huán)境執(zhí)行運(yùn)算結(jié)果(還是M2)录平,因此this指向全局環(huán)境麻车。

避免多層this

由于this的指向是不確定的,所以切勿在函數(shù)中包含多層的this斗这。

var o = {
  f1: function () {
    console.log(this);
    var f2 = function () {
      console.log(this);
    }();
  }
}
o.f1()
// Object
// Window

上面代碼等價(jià)于

var temp = function () {
  console.log(this);
};
var o = {
  f1: function () {
    console.log(this);
    var f2 = temp();
  }
}

當(dāng)我們把代碼修改為

var o = {
  f1: function() {
    console.log(this);
    var that = this;
    var f2 = function() {
      console.log(that);
    }();
  }
}
o.f1()
// Object
// Object

上面代碼定義了變量that动猬,固定指向外層的this,然后在內(nèi)層使用that表箭,就不會(huì)發(fā)生this指向的改變赁咙。

避免數(shù)組處理方法中的this

數(shù)組的map和foreach方法,允許提供一個(gè)函數(shù)作為參數(shù)燃逻。這個(gè)函數(shù)內(nèi)部不應(yīng)該使用this序目。

var o = {
  v: 'hello',
  p: [ 'a1', 'a2' ],
  f: function f() {
    this.p.forEach(function (item) {
      console.log(this.v + ' ' + item);
    });
  }
}
o.f()
// undefined a1
// undefined a2

上面代碼相當(dāng)于

var temp = function(){
   o.p.forEach(function (item) {
      console.log(this.v + ' ' + item);
    });
} //this指向全局變量
var o = {
  v: 'hello',
  p: [ 'a1', 'a2' ],
  f: temp() 
}
o.f()
// undefined a1
// undefined a2

我們同樣可以這樣修改

var o = {
  v: 'hello',
  p: [ 'a1', 'a2' ],
  f: function f() {
    var that = this;
    this.p.forEach(function (item) {
      console.log(that.v+' '+item);
    });
  }
}
o.f()
// hello a1
// hello a2

或者將this當(dāng)作foreach方法的第二個(gè)參數(shù),固定它的運(yùn)行環(huán)境伯襟。

var o = {
  v: 'hello',
  p: [ 'a1', 'a2' ],
  f: function f() {
    this.p.forEach(function (item) {
      console.log(this.v + ' ' + item);
    }, this);
  }
}
o.f()
// hello a1
// hello a2

bind方法

bind方法用于將函數(shù)體內(nèi)的this綁定到某個(gè)對(duì)象猿涨,然后返回一個(gè)新函數(shù)。

var counter = {
  count: 0,
  inc: function () {
    this.count++;
  }
};
var func = counter.inc;
func();
counter.count // 0
count // NaN

上面代碼中姆怪,函數(shù)func是在全局環(huán)境中運(yùn)行的叛赚,這時(shí)inc內(nèi)部的this指向頂層對(duì)象window,所以counter.count是不會(huì)變的稽揭,反而創(chuàng)建了一個(gè)全局變量count俺附。因?yàn)閣indow.count原來等于undefined,進(jìn)行遞增運(yùn)算后undefined++就等于NaN溪掀。

var func = counter.inc.bind(counter);
func();
counter.count
//1

使用bind方法將inc方法綁定到counter以后事镣,再運(yùn)行func就會(huì)得到正確結(jié)果。

小結(jié)

對(duì)于this揪胃,我們只要記得其本質(zhì)就是call函數(shù)時(shí)傳入的第一個(gè)參數(shù)璃哟,如果函數(shù)調(diào)用形式不是 call 形式,請(qǐng)將其轉(zhuǎn)換為 call 形式喊递,函數(shù)的this值可以用call改變随闪,也可以用bind改變默認(rèn)的this值。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末骚勘,一起剝皮案震驚了整個(gè)濱河市铐伴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌俏讹,老刑警劉巖当宴,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異泽疆,居然都是意外死亡即供,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門于微,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逗嫡,“玉大人青自,你說我怎么就攤上這事∏ぃ” “怎么了延窜?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)抹锄。 經(jīng)常有香客問我逆瑞,道長(zhǎng),這世上最難降的妖魔是什么伙单? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任获高,我火速辦了婚禮,結(jié)果婚禮上吻育,老公的妹妹穿的比我還像新娘念秧。我一直安慰自己,他們只是感情好布疼,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布摊趾。 她就那樣靜靜地躺著,像睡著了一般游两。 火紅的嫁衣襯著肌膚如雪砾层。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天贱案,我揣著相機(jī)與錄音肛炮,去河邊找鬼。 笑死宝踪,一個(gè)胖子當(dāng)著我的面吹牛侨糟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播肴沫,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼粟害,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼蕴忆!你這毒婦竟也來了颤芬?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤套鹅,失蹤者是張志新(化名)和其女友劉穎站蝠,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體卓鹿,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡菱魔,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吟孙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片澜倦。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡聚蝶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出藻治,到底是詐尸還是另有隱情碘勉,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布桩卵,位于F島的核電站验靡,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏雏节。R本人自食惡果不足惜胜嗓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望钩乍。 院中可真熱鬧辞州,春花似錦、人聲如沸件蚕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)排作。三九已至牵啦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間妄痪,已是汗流浹背哈雏。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留衫生,地道東北人裳瘪。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像罪针,于是被迫代替她去往敵國(guó)和親彭羹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 官方中文版原文鏈接 感謝社區(qū)中各位的大力支持,譯者再次奉上一點(diǎn)點(diǎn)福利:阿里云產(chǎn)品券墓阀,享受所有官網(wǎng)優(yōu)惠毡惜,并抽取幸運(yùn)大...
    HetfieldJoe閱讀 6,926評(píng)論 15 54
  • 與其他語(yǔ)言相比,函數(shù)的this關(guān)鍵字在JavaScript中的表現(xiàn)略有不同斯撮,此外经伙,在嚴(yán)格模式和非嚴(yán)格模式之間也會(huì)有...
    codingC閱讀 574評(píng)論 0 0
  • 特別說明帕膜,為便于查閱枣氧,文章轉(zhuǎn)自https://github.com/getify/You-Dont-Know-JS...
    殺破狼real閱讀 691評(píng)論 0 1
  • 第5章 引用類型(返回首頁(yè)) 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,233評(píng)論 0 4
  • 窗外疾馳的車輛 驅(qū)趕著深秋的冷霧 汽笛聲陣陣催促我忙碌 塵世那漸行漸遠(yuǎn)的腳步 詩(shī)歌在柴米油鹽中荒蕪 撥開雜草叢生阡...
    古月ypc閱讀 185評(píng)論 0 0