淺談this,new旬盯,call台妆,apply

0.關(guān)于this是指什么

  • 其實(shí)可以這么概括翎猛,this屬于調(diào)用被調(diào)用的方法的主體胖翰,也就是,誰調(diào)用切厘,誰就是this萨咳。
  • 雖然說起來這么簡單,但是上面的話里面的概念其實(shí)涉及到:作為方法的調(diào)用(function)的this疫稿;作為構(gòu)造函數(shù)里的this培他;作為call或者apply的this鹃两。
  • 以上三個概念,又涉及到j(luò)s里的對象創(chuàng)建舀凛,和方法的繼承俊扳,所以,要弄清楚this猛遍,就要弄清楚js里的對象創(chuàng)建和繼承機(jī)制馋记。

1.作為方法調(diào)用(function)的this

這個是最為簡單的,但也可以分為幾種情況懊烤,我們寫一個文件梯醒,叫functionThis.js
1.1 有如下代碼:

function fnThis(){
    console.log(this);
}
fnThis();

打印結(jié)果如下:

1-1

可以看到this當(dāng)前是指向window,這個很好理解腌紧,因?yàn)閠his是指向調(diào)用者茸习,而fnThis沒有調(diào)用者,沒有調(diào)用者就默認(rèn)為window壁肋。

1.2 我們在文件繼續(xù)添加代碼号胚,如下

var obj = {
    fnThis: function(){
        console.log(this);
    }
}
obj.fnThis();
var objIns = obj.fnThis;
objIns();

打印結(jié)果如下:

1-2

可以看到,第1行的打印this是obj浸遗,第2行是window涕刚,會這樣的差異是因?yàn)椋簅bj.fnThis()的調(diào)用者是obj,所以this指向obj乙帮;而objIns()沒有調(diào)用者杜漠,默認(rèn)為window。

2.作為構(gòu)造函數(shù)里的this

這里我們的demo文件為constructorThis.js

2.1 說到這里又要提一下構(gòu)造函數(shù)察净,構(gòu)造函數(shù)驾茴,就是可以構(gòu)造一個對象的函數(shù)類,js里面最簡單的莫過于直接定義一個對象氢卡,這個對象有一些屬性的方法锈至,然后用的時候直接拿來用,像我們functionThis.js這個文件里的就是這種情況译秦,這是直接定義峡捡,另外還有一些其他的方式就先不展開講了,下面的例子以比較常見的構(gòu)造函數(shù)的形式為例筑悴,至于為什么要用構(gòu)造函數(shù)们拙,簡單地講就是可以用面向?qū)ο蟮男问饺ゾ幊蹋衫^承阁吝,等砚婆。

2.2 測試代碼如下:

var thisObj;
var ConstructorThis = function(params){
    this.myParams = params;
    console.log(this);
    thisObj = this;
}
ConstructorThis.prototype.sayParams = function(){
    console.log(this.myParams);
}
var obj = new ConstructorThis('hi');
console.log(obj);
console.log(obj === thisObj)
obj.sayParams();

打印結(jié)果如下:

2-2

我們可以看到第1行和第2行打印的對象從字面上看是一樣的(字面一樣不等于兩個對象是同一個東西,后續(xù)可以自行初始化幾個對象進(jìn)行類似的對比驗(yàn)證)突勇,我們?yōu)榱蓑?yàn)證這個this是否就是obj装盯,把this賦值給外部的thisObj并進(jìn)行比較坷虑,結(jié)果是true,說明構(gòu)造函數(shù)內(nèi)的this確實(shí)就是new 構(gòu)造函數(shù)() 后的對象埂奈。

2.3 如此一來迄损,因?yàn)闃?gòu)造函數(shù)需要用new關(guān)鍵字實(shí)例化一個對象,那么和1-2作為方法的調(diào)用的情況相比账磺,this似乎就不是指向被調(diào)用者了海蔽?

實(shí)際上:

var obj = new ConstructorThis('hi');

等價于:

var obj = {};
obj.__proto__ = ConstructorThis.prototype;
ConstructorThis.call(obj, 'hi');

將第一個代碼塊改為下面三行的代碼塊,我們再看一下打印結(jié)果:

2-3

與2-2的情況是一致的绑谣。

也就是說党窜,new 構(gòu)造函數(shù)() 干了這么一件事情拴袭,第一步巨朦,創(chuàng)建一個空的對象嬉荆;第二步全跨,把空對象的原型指向構(gòu)造函數(shù)的原型闷袒;第三步卸伞,再根據(jù)call傳入?yún)?shù)('hi')速缨,同時把構(gòu)造函數(shù)內(nèi)部的this指向這個空對象褒翰,這樣一來就完成了構(gòu)造函數(shù)原型鏈的繼承(第二步)和自身屬性的賦值(第三步)欲间;最后返回新創(chuàng)建的對象楚里。

構(gòu)造函數(shù)內(nèi)部this等于新創(chuàng)建的對象,關(guān)鍵就在第三步猎贴,用了call方法把創(chuàng)建的對象指向了內(nèi)部的this班缎,call和apply方法會在接下來講∷剩總之达址,構(gòu)造函數(shù)內(nèi)部的this指向用new創(chuàng)建的新對象。

3.作為call或者apply的this

這里我們?nèi)匀粍?chuàng)建一個demo文件callThis.js

3.1 call或者apply的作用就是改變某個方法的運(yùn)行環(huán)境趁耗,也就是改變內(nèi)部this關(guān)鍵字的指向沉唠,正因?yàn)橛羞@樣的作用,也在js的繼承機(jī)制中其中有著顯著的作用苛败。正如2-3我們講到的一樣满葛,構(gòu)造函數(shù)用call把創(chuàng)建的一個類指向了內(nèi)部的this關(guān)鍵字,因此構(gòu)造函數(shù)類可以作為一個類被繼承罢屈,每個不同的實(shí)例通過內(nèi)部的this被賦予了不同的屬性嘀韧。

3.2 call和apply的用法其實(shí)很簡單,我們看如下代碼:

var CallThis = function(params){
    console.log(this)
    this.myParams = params;
}
CallThis.call();
var obj = {otherParams: 'ok'};
CallThis.call(obj, 'hi');
console.log(obj);

打印結(jié)果如下:

3-2

第一次call沒傳任何參數(shù)儡遮,內(nèi)部的this打印出來是window乳蛾,這在第一部分的時候已經(jīng)說明了;第二次call的時候第一個參數(shù)是一個對象鄙币,第二個參數(shù)對應(yīng)構(gòu)造函數(shù)的一個參數(shù)肃叶,可以看到this指向了obj,然后obj被添加了myParams屬性十嘿,因此 構(gòu)造函數(shù).call(obj, args)這種形式就是通過call方法把this指向obj因惭,args是傳入構(gòu)造函數(shù)內(nèi)部的參數(shù),需要傳多個參數(shù)是這樣子的 構(gòu)造函數(shù).call(obj, args, args1, ..., argsN)绩衷,第一個參數(shù)就是把this指向的對象蹦魔,這和我們在2-3說到的,new的步驟分解咳燕,第三步是一致的勿决。

apply和call的用法類似,構(gòu)造函數(shù).call(obj, args, args1, ..., argsN) 等同于 構(gòu)造函數(shù).call(obj, [args, args1, ..., argsN])招盲,我們修改一下代碼低缩,將

CallThis.call(obj, 'hi');

替換為

CallThis.apply(obj, ['hi']);

可見,打印結(jié)果一致:

3-2-1

即曹货,call和apply都能把上下文運(yùn)行到具體的this環(huán)境里咆繁,不同的只是傳參的形式,call參數(shù)的傳遞是分開傳遞顶籽,而apply是作為數(shù)組傳遞玩般。

4.總結(jié)

到這里就基本把this涉及到的情況說完了,包括作為方法的調(diào)用(function)的this礼饱;作為構(gòu)造函數(shù)里的this坏为;作為call或者apply的this;第二和第三種情況本質(zhì)上是統(tǒng)一的镊绪。

這算是第一次寫比較完整的文章久脯,大部分是自己的理解,當(dāng)然前期學(xué)習(xí)階段也參考了一些資料镰吆,若有不當(dāng)之處帘撰,還請指正,若有寶貴意見万皿,也可以多多交流摧找。

具體的實(shí)例代碼和demo地址:

https://github.com/CHristopherkeith/front-end-summary-this-new

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市牢硅,隨后出現(xiàn)的幾起案子蹬耘,更是在濱河造成了極大的恐慌,老刑警劉巖减余,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件综苔,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)如筛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門堡牡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人杨刨,你說我怎么就攤上這事晤柄。” “怎么了妖胀?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵芥颈,是天一觀的道長。 經(jīng)常有香客問我赚抡,道長爬坑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任涂臣,我火速辦了婚禮盾计,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘肉康。我一直安慰自己闯估,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布吼和。 她就那樣靜靜地躺著涨薪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪炫乓。 梳的紋絲不亂的頭發(fā)上刚夺,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天,我揣著相機(jī)與錄音末捣,去河邊找鬼侠姑。 笑死,一個胖子當(dāng)著我的面吹牛箩做,可吹牛的內(nèi)容都是我干的莽红。 我是一名探鬼主播,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼邦邦,長吁一口氣:“原來是場噩夢啊……” “哼安吁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起燃辖,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤鬼店,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后黔龟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體妇智,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡滥玷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了巍棱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惑畴。...
    茶點(diǎn)故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖拉盾,靈堂內(nèi)的尸體忽然破棺而出桨菜,到底是詐尸還是另有隱情豁状,我是刑警寧澤捉偏,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站泻红,受9級特大地震影響夭禽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜谊路,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一讹躯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缠劝,春花似錦潮梯、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至脱羡,卻和暖如春萝究,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背锉罐。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工帆竹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人脓规。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓栽连,卻偏偏與公主長得像,于是被迫代替她去往敵國和親侨舆。 傳聞我的和親對象是個殘疾皇子秒紧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評論 2 350

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