摘要:箭頭函數(shù)的尋值行為與普通變量相同,在作用域中逐級尋找。題目這次通過構造函數(shù)來創(chuàng)建一個對象,并執(zhí)行相同的個方法。
我們知道this綁定規(guī)則一共有5種情況:
1、默認綁定(嚴格/非嚴格模式)
2、隱式綁定
3、顯式綁定
4、new綁定
5、箭頭函數(shù)綁定
其實大部分情況下可以用一句話來概括,this總是指向調(diào)用該函數(shù)的對象。
但是對于箭頭函數(shù)并不是這樣,是根據(jù)外層(函數(shù)或者全局)作用域(詞法作用域)來決定this。
對于箭頭函數(shù)的this總結如下:
箭頭函數(shù)不綁定this,箭頭函數(shù)中的this相當于普通變量。
箭頭函數(shù)的this尋值行為與普通變量相同,在作用域中逐級尋找。
箭頭函數(shù)的this無法通過bind,call,apply來直接修改(可以間接修改)。
改變作用域中this的指向可以改變箭頭函數(shù)的this。
eg. function closure(){()=>{//code }},在此例中,我們通過改變封包環(huán)境closure.bind(another)(),來改變箭頭函數(shù)this的指向。
題目1/** * 非嚴格模式 */ var name = "window" var person1 = { name: "person1", show1: function () { console.log(this.name) }, show2: () => console.log(this.name), show3: function () { return function () { console.log(this.name) } }, show4: function () { return () => console.log(this.name) } } var person2 = { name: "person2" } person1.show1() person1.show1.call(person2) person1.show2() person1.show2.call(person2) person1.show3()() person1.show3().call(person2) person1.show3.call(person2)() person1.show4()() person1.show4().call(person2) person1.show4.call(person2)()
空
白
占
位
符
正確答案如下:
person1.show1() // person1,隱式綁定,this指向調(diào)用者 person1 person1.show1.call(person2) // person2,顯式綁定,this指向 person2 person1.show2() // window,箭頭函數(shù)綁定,this指向外層作用域,即全局作用域 person1.show2.call(person2) // window,箭頭函數(shù)綁定,this指向外層作用域,即全局作用域 person1.show3()() // window,默認綁定,這是一個高階函數(shù),調(diào)用者是window // 類似于`var func = person1.show3()` 執(zhí)行`func()` person1.show3().call(person2) // person2,顯式綁定,this指向 person2 person1.show3.call(person2)() // window,默認綁定,調(diào)用者是window person1.show4()() // person1,箭頭函數(shù)綁定,this指向外層作用域,即person1函數(shù)作用域 person1.show4().call(person2) // person1,箭頭函數(shù)綁定, // this指向外層作用域,即person1函數(shù)作用域 person1.show4.call(person2)() // person2
最后一個person1.show4.call(person2)()有點復雜,我們來一層一層的剝開。
1、首先是var func1 = person1.show4.call(person2),這是顯式綁定,調(diào)用者是person2,show4函數(shù)指向的是person2。
2、然后是func1(),箭頭函數(shù)綁定,this指向外層作用域,即person2函數(shù)作用域
首先要說明的是,箭頭函數(shù)綁定中,this指向外層作用域,并不一定是第一層,也不一定是第二層。
因為沒有自身的this,所以只能根據(jù)作用域鏈往上層查找,直到找到一個綁定了this的函數(shù)作用域,并指向調(diào)用該普通函數(shù)的對象。
題目2這次通過構造函數(shù)來創(chuàng)建一個對象,并執(zhí)行相同的4個show方法。
/** * 非嚴格模式 */ var name = "window" function Person (name) { this.name = name; this.show1 = function () { console.log(this.name) } this.show2 = () => console.log(this.name) this.show3 = function () { return function () { console.log(this.name) } } this.show4 = function () { return () => console.log(this.name) } } var personA = new Person("personA") var personB = new Person("personB") personA.show1() personA.show1.call(personB) personA.show2() personA.show2.call(personB) personA.show3()() personA.show3().call(personB) personA.show3.call(personB)() personA.show4()() personA.show4().call(personB) personA.show4.call(personB)()
空
白
占
位
符
正確答案如下:
personA.show1() // personA,隱式綁定,調(diào)用者是 personA personA.show1.call(personB) // personB,顯式綁定,調(diào)用者是 personB personA.show2() // personA,首先personA是new綁定,產(chǎn)生了新的構造函數(shù)作用域, // 然后是箭頭函數(shù)綁定,this指向外層作用域,即personA函數(shù)作用域 personA.show2.call(personB) // personA,同上 personA.show3()() // window,默認綁定,調(diào)用者是window personA.show3().call(personB) // personB,顯式綁定,調(diào)用者是personB personA.show3.call(personB)() // window,默認綁定,調(diào)用者是window personA.show4()() // personA,箭頭函數(shù)綁定,this指向外層作用域,即personA函數(shù)作用域 personA.show4().call(personB) // personA,箭頭函數(shù)綁定,call并沒有改變外層作用域, // this指向外層作用域,即personA函數(shù)作用域 personA.show4.call(personB)() // personB,解析同題目1,最后是箭頭函數(shù)綁定, // this指向外層作用域,即改變后的person2函數(shù)作用域
題目一和題目二的區(qū)別在于題目二使用了new操作符。
上期思考題解使用 new 操作符調(diào)用構造函數(shù),實際上會經(jīng)歷一下4個步驟:
創(chuàng)建一個新對象;
將構造函數(shù)的作用域賦給新對象(因此this就指向了這個新對象);
執(zhí)行構造函數(shù)中的代碼(為這個新對象添加屬性);
返回新對象。
依次給出console.log輸出的數(shù)值。
var num = 1; var myObject = { num: 2, add: function() { this.num = 3; (function() { console.log(this.num); this.num = 4; })(); console.log(this.num); }, sub: function() { console.log(this.num) } } myObject.add(); console.log(myObject.num); console.log(num); var sub = myObject.sub; sub();
答案有兩種情況,分為嚴格模式和非嚴格模式。
嚴格模式下,報錯。TypeError: Cannot read property "num" of undefined
非嚴格模式下,輸出:1、3、3、4、4
解答過程:
var num = 1; var myObject = { num: 2, add: function() { this.num = 3; // 隱式綁定 修改 myObject.num = 3 (function() { console.log(this.num); // 默認綁定 輸出 1 this.num = 4; // 默認綁定 修改 window.num = 4 })(); console.log(this.num); // 隱式綁定 輸出 3 }, sub: function() { console.log(this.num) // 因為丟失了隱式綁定的myObject,所以使用默認綁定 輸出 4 } } myObject.add(); // 1 3 console.log(myObject.num); // 3 console.log(num); // 4 var sub = myObject.sub;// 丟失了隱式綁定的myObject sub(); // 4
內(nèi)容來自評論區(qū):【進階3-1期】JavaScript深入之史上最全--5種this綁定全面解析
本期思考題分別給出console.log輸出的內(nèi)容。
var obj = { say: function () { function _say() { console.log(this); } console.log(obj); return _say.bind(obj); }() } obj.say()參考
從這兩套題,重新認識JS的this、作用域、閉包、對象進階系列目錄
【進階1期】 調(diào)用堆棧
【進階2期】 作用域閉包
【進階3期】 this全面解析
【進階4期】 深淺拷貝原理
【進階5期】 原型Prototype
【進階6期】 高階函數(shù)
【進階7期】 事件機制
【進階8期】 Event Loop原理
【進階9期】 Promise原理
【進階10期】Async/Await原理
【進階11期】防抖/節(jié)流原理
【進階12期】模塊化詳解
【進階13期】ES6重難點
【進階14期】計算機網(wǎng)絡概述
【進階15期】瀏覽器渲染原理
【進階16期】webpack配置
【進階17期】webpack原理
【進階18期】前端監(jiān)控
【進階19期】跨域和安全
【進階20期】性能優(yōu)化
【進階21期】VirtualDom原理
【進階22期】Diff算法
【進階23期】MVVM雙向綁定
【進階24期】Vuex原理
【進階25期】Redux原理
【進階26期】路由原理
【進階27期】VueRouter源碼解析
【進階28期】ReactRouter源碼解析
交流進階系列文章匯總:https://github.com/yygmind/blog,內(nèi)有優(yōu)質(zhì)前端資料,歡迎領取,覺得不錯點個star。
我是木易楊,網(wǎng)易高級前端工程師,跟著我每周重點攻克一個前端面試重難點。接下來讓我?guī)阕哌M高級前端的世界,在進階的路上,共勉!
文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/100740.html
摘要:首次運行代碼時,會創(chuàng)建一個全局執(zhí)行上下文并到當前的執(zhí)行棧中。執(zhí)行上下文的創(chuàng)建執(zhí)行上下文分兩個階段創(chuàng)建創(chuàng)建階段執(zhí)行階段創(chuàng)建階段確定的值,也被稱為。 (關注福利,關注本公眾號回復[資料]領取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導) 本周正式開始前端進階的第一期,本周的主題是調(diào)用堆棧,,今天是第一天 本計劃一共28期,每期重點攻克一個面試重難點,如果你還不了解本進...
摘要:引言上一節(jié)介紹了高階函數(shù)的定義,并結合實例說明了使用高階函數(shù)和不使用高階函數(shù)的情況。我們期望函數(shù)輸出,但是實際上調(diào)用柯里化函數(shù)時,所以調(diào)用時就已經(jīng)執(zhí)行并輸出了,而不是理想中的返回閉包函數(shù),所以后續(xù)調(diào)用將會報錯。引言 上一節(jié)介紹了高階函數(shù)的定義,并結合實例說明了使用高階函數(shù)和不使用高階函數(shù)的情況。后面幾部分將結合實際應用場景介紹高階函數(shù)的應用,本節(jié)先來聊聊函數(shù)柯里化,通過介紹其定義、比較常見的...
摘要:本計劃一共期,每期重點攻克一個面試重難點,如果你還不了解本進階計劃,點擊查看前端進階的破冰之旅本期推薦文章深入之執(zhí)行上下文棧和深入之變量對象,由于微信不能訪問外鏈,點擊閱讀原文就可以啦。 (關注福利,關注本公眾號回復[資料]領取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導) 本周正式開始前端進階的第一期,本周的主題是調(diào)用堆棧,今天是第二天。 本計劃一共28期,每期...
摘要:在嚴格模式下調(diào)用函數(shù)則不影響默認綁定?;卣{(diào)函數(shù)丟失綁定是非常常見的。因為直接指定的綁定對象,稱之為顯示綁定。調(diào)用時強制把的綁定到上顯示綁定無法解決丟失綁定問題。 (關注福利,關注本公眾號回復[資料]領取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導) 本周正式開始前端進階的第三期,本周的主題是this全面解析,今天是第9天。 本計劃一共28期,每期重點攻克一個面試重...
摘要:本期推薦文章類內(nèi)存泄漏及如何避免,由于微信不能訪問外鏈,點擊閱讀原文就可以啦。四種常見的內(nèi)存泄漏劃重點這是個考點意外的全局變量未定義的變量會在全局對象創(chuàng)建一個新變量,如下。因為老版本的是無法檢測節(jié)點與代碼之間的循環(huán)引用,會導致內(nèi)存泄漏。 (關注福利,關注本公眾號回復[資料]領取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導) 本周正式開始前端進階的第一期,本周的主題...
閱讀 3640·2021-11-18 10:02
閱讀 3179·2019-08-29 18:34
閱讀 3481·2019-08-29 17:00
閱讀 496·2019-08-29 12:35
閱讀 823·2019-08-28 18:22
閱讀 2069·2019-08-26 13:58
閱讀 1748·2019-08-26 10:39
閱讀 2746·2019-08-26 10:11