日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

难缠的this

發(fā)布時間:2023/12/20 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 难缠的this 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在深入了解JavaScript中this關鍵字之前,有必要先退一步,看一下為什么this關鍵字很重要。this允許復用函數(shù)時使用不同的上下文。換句話說,this關鍵字允許在調(diào)用函數(shù)或方法時決定哪個對象才是焦點。之后討論的所有東西都是基于這個理念。我們希望能夠在不同的上下文或在不同的對象中復用函數(shù)或方法。

我們關注的第一件事是如何判斷this關鍵字的引用。當你試圖回答這個問題時,需要問自己的第一個也是最重要的問題是“這個函數(shù)在哪里被調(diào)用”。判斷this引用什么的唯一方法就是看使用this關鍵字的這個方法在哪里被調(diào)用

一 隱式綁定

請記住,判斷this指向要看使用this關鍵字的這個方法在哪里被調(diào)用。假如有下面一個對象

const obj = {title: 'test',fn(): {console.dir(this.title)} } 復制代碼

如果想調(diào)用fn方法,就要

obj.fn() 復制代碼

這就把我們帶到隱式綁定規(guī)則的主要關鍵點。為了判斷 this 關鍵字的引用,函數(shù)被調(diào)用時先看一看點號左側(cè)。如果有“點”就查看點左側(cè)的對象,這個對象就是 this 的引用。 在上面的例子中,obj 在“點號左側(cè)”意味著 this 引用了 obj 對象。所以就好像 在 fn 方法的內(nèi)部 JavaScript 解釋器把 this 變成了 obj。 再看如下例子

const obj = {title: 'test',fn() {console.dir(this.title)},sub: {title: 'test2',fn() {console.dir(this.title)}} } obj.fn() // test obj.sub.fn() // test2 復制代碼

每當判斷 this 的引用時,都需要查看調(diào)用過程,并確認“點的左側(cè)”是什么。第一個調(diào)用,obj 在點左側(cè)意味著 this 將引用 obj。第二次調(diào)用中,sub 在點的左側(cè)意味著 this 引用 sub。 所以大多數(shù)情況下,檢查使用this方法的點的左側(cè)是什么。如果沒有點呢,繼續(xù)往下看。

二 顯示綁定

如果fn只是一個獨立的函數(shù),如下

fn() {console.dir(this.title) } const obj = {title: 'test' } 復制代碼

為了判斷this的引用必須先查看這個函數(shù)的調(diào)用位置,那怎樣才能讓fn調(diào)用的時候?qū)his指向this?我們并不能再像上面那樣簡單的使用obj.fn(),因為obj并沒有fn方法。但是在js中,每個函數(shù)都有一個方法call,正好解決這個問題。

"call" 是每個函數(shù)都有的方法,它允許在調(diào)用函數(shù)時為函數(shù)指定上下文

所以,可以用下面的方式調(diào)用fn方法

fn.call(obj) 復制代碼

call是每個函數(shù)都有的屬性,并且傳遞給它的第一個參數(shù)會作為函數(shù)調(diào)用時的上下文。也就是說,this會指向傳遞給call的第一個參數(shù)

這就是顯示綁定的基礎,因為我們明確的使用call指定了this的引用。 現(xiàn)在將fn改動一下

fn(name1, name2){console.dir(`${this.title} is ${name1} and ${name2}`) } 復制代碼

此時使用call方法就要如下

fn.call(obj, '張三', '李四') 復制代碼

使用call方法需要將參數(shù)一個一個的傳遞進去,參數(shù)過多,就會越麻煩。此時apply方法就可以解決。

apply和call本質(zhì)相同,但不是一個個傳遞參數(shù),可以用數(shù)組傳參且apply會在函數(shù)中為你自動展開。

const arr = ['張三', '李四'] fn.apply(obj, arr) 復制代碼

除了call和apply可以顯示綁定this外,還有bind方法也可以

bind和call調(diào)用方式完全相同,不同的是bind不會立即調(diào)用函數(shù),而是返回一個能以后調(diào)用的新函數(shù)

const newFn = fn.bind(obj, '張三', '李四') newFn() 復制代碼

傳入的不是對象: 如果傳入了一個原始值(字符串,布爾類型,數(shù)字類型),來當做this的綁定對象,這個原始值轉(zhuǎn)換成它的對象形式。 如果把null或者undefined作為this的綁定對象傳入call/apply/bind,這些值會在調(diào)用時被忽略,實際應用的是默認綁定規(guī)則

三 new 綁定

function fn(a) {this.a = a } const bar = new fn(2) console.log(bar.a) // 2 復制代碼

用new操作符創(chuàng)建對象時會發(fā)生如下步驟:

  • 創(chuàng)建一個全新的Object對象實例
  • 將構(gòu)造函數(shù)的執(zhí)行對象賦給新生成的這個實例
  • 這個新對象會綁定到函數(shù)調(diào)用的this
  • 如果函數(shù)沒有返回其他對象,那么new表達式中的函數(shù)調(diào)用會自動返回這個新對象 規(guī)則:使用構(gòu)造調(diào)用的時候,this會自動綁定在new期間創(chuàng)建的對象上
  • 所以,new fn(2)就相當于

    const newObj = new Object() newObj.a = a 復制代碼

    還有一種特殊情況,就是當構(gòu)造函數(shù)通過 "return" 返回的是一個對象的時候,此次運算的最終結(jié)果返回的就是這個對象,而不是新創(chuàng)建的對象,因此 this 在這種情況下并沒有什么用。注意,返回函數(shù)也是返回新的對象,函數(shù)對象

    function fn(a) {this.a = areturn {} } const bar = new fn(2) console.log(bar.a) // undefined 復制代碼

    四 window 綁定

    fn() {console.dir(this.title) } const obj = {title: 'test' } fn() // undefined 復制代碼

    當點的左側(cè)沒有任何東西,也沒有通過call、apply、bind方法調(diào)用,也沒有new關鍵字,this就會指向了window。

    window.title = '全局' fn() {console.dir(this.title) } fn() // 全局 復制代碼

    在ES5添加的嚴格模式中,this不會指向window對象,而是保持為undefined

    五 四種綁定的優(yōu)先規(guī)則

    顯式綁定 > 隱式綁定 > 默認綁定 new綁定 > 隱式綁定 > 默認綁定

    六 丟失的this

    在某些情況下會丟失 this 的指向,此時,我們就需要借助 call、apply 和 bind 來改變 this 的指向問題。 示例一,當fn方法作為obj對象的屬性調(diào)用時,this指向obj對象,當另外一個變量引用fn方法時,因為它作為普通函數(shù)調(diào)用,所以this指向window對象

    const obj = {title: 'test',fn: function() {console.dir(this.title)} } obj.fn() // test const getTitle = obj.fn getTitle() // undefined 復制代碼

    這種方式實際就是函數(shù)調(diào)用時,并沒有上下文對象,只是對函數(shù)的引用,同樣的問題,還發(fā)生在傳入回調(diào)函數(shù)中

    test(obj.fn) // 傳入函數(shù)的引用,調(diào)用時也是沒有上下文 復制代碼

    示例二,即使在函數(shù)內(nèi)部定義的函數(shù),如果它作為普通對象調(diào)用,this同樣指向window對象

    const obj = {title: 'test',name: '張三',fn: function() {console.dir(this.title)function getName(){console.dir(this.name)}getName()} } obj.fn() // test// undefined 復制代碼

    七 練習

    var xuuu = 123 function test() {var xuuu = 456this.aa = 6666 return function() {console.log(xuuu)console.log(this.aa)console.log(this.xuuu) }var sdf=new test() sdf() // 456, undefined, 123 test()() // 456,6666,123 復制代碼

    結(jié)論:第一種情況的中this.aa指向sdf,return中this指向全局對象window;第二種情況中兩次this都指向window

    八 箭頭函數(shù)的this

    在以往的函數(shù)中,this 有各種各樣的指向(隱式綁定,顯示綁定,new 綁定, window 綁定......),雖然靈活方便,但由于不能在定義函數(shù)時而直到實際調(diào)用時才能知道 this 指向,很容易給開發(fā)者帶來諸多困擾。比如下面的代碼

    function User() {this.name = 'John'setTimeout(function greet() {console.log(`Hello, my name is ${this.name}`) // Hello, my name is console.log(this) // window}, 1000) }const user = new User() 復制代碼

    如果想把greet里面的this指向user對象該怎么辦呢? 1 使用閉包

    function User(){const self = thisthis.name = 'John'setTimeout(function greet() {console.log(`Hello, my name is ${self.name}`) // Hello, my name is Johnconsole.log(self) // User {name: "John"}}, 1000) }const user = new User() 復制代碼

    ** 2 使用顯示綁定bind **

    function User() {this.name = 'John';setTimeout(function greet() {console.log(`Hello, my name is ${this.name}`); // Hello, my name is Johnconsole.log(this); // User {name: "John"}}.bind(this)(), 1000); }const user = new User(); 復制代碼

    ** 利用 setTimeout 的可以傳更多參數(shù)的特性 **

    function User() {this.name = 'John';setTimeout(function greet(self) {console.log(`Hello, my name is ${self.name}`); // Hello, my name isconsole.log(self); // window}, 1000, this); }const user = new User(); 復制代碼

    ** 箭頭函數(shù)如何解決 **

    function User() {this.name = 'John';setTimeout(() => {console.log(`Hello, my name is ${this.name}`); // Hello, my name is Johnconsole.log(this); // User {name: "John"}}, 1000); }const user = new User(); 復制代碼

    **箭頭函數(shù)在自己的作用域內(nèi)不綁定 this,即沒有自己的 this,**如果要使用 this ,就會指向定義時所在的作用域的 this 值。在上面的代碼中即指向 User 函數(shù)的 this,而 User 函數(shù)通過 new 綁定,所以 this 實際指向 user 對象

    function foo() {return () => {console.log(this.a);}; } let obj1 = {a: 2 }; let obj2 = {a: 22 }; let bar = foo.call(obj1); // foo this指向obj1 bar.call(obj2); // 輸出2 這里執(zhí)行箭頭函數(shù) 并試圖綁定this指向到obj2 但并不成功 復制代碼

    結(jié)論: 1、箭頭函數(shù)沒有自己的this,它的this繼承于它外面第一個不是箭頭函數(shù)的函數(shù)的this指向。 2、箭頭函數(shù)的 this 一旦綁定了上下文,就不會被任何代碼改變 3、箭頭函數(shù)使用call、apply、bind時,會自動忽略掉第一個參數(shù) 4、嚴格模式并不影響箭頭函數(shù)自己的this

    九 最后的圖片

    總結(jié)

    以上是生活随笔為你收集整理的难缠的this的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 欧美一区二区性久久久 | 伦一理一级一a一片 | 国产综合婷婷 | 欧美 日本 国产 | 少妇人妻偷人精品无码视频 | 日本妇女毛茸茸 | 丝袜+亚洲+另类+欧美+变态 | 一级黄色影院 | 青草操| 嫩草嫩草嫩草嫩草 | 国产另类在线 | 婷婷国产一区二区三区 | 91丝袜一区在线观看 | 国产精品三 | 国产激情无码一区二区三区 | 天天操操操操 | 天堂色区 | 视频在线观看91 | 九色porny视频 | 国产黄色小视频在线观看 | 成年人网站黄色 | 亚洲一区二区三区四区 | 热久久精 | 色欲久久久天天天精品综合网 | 老外黄色一级片 | 先锋影音一区二区 | 女人被狂躁c到高潮喷水电影 | 爱情岛论坛永久入口 | 筱田优av | 麻豆精品国产 | 日日夜夜拍 | 涩涩视频在线 | 欧美日批 | 日本高清免费观看 | 成人毛片视频免费看 | 91麻豆精品国产91久久久更新时间 | 亚洲一区图片 | 亚洲激情二区 | 国产精品久久久久久久久久久久久久 | 少妇人妻综合久久中文字幕 | 99re这里只有精品在线 | 解开乳罩喂领导吃奶 | 欧美日韩一级二级三级 | 亚洲性综合 | 欧美第二区 | 天天天天色 | 椎名由奈av一区二区三区 | 最新中文字幕免费视频 | 亚洲色图网站 | a天堂视频在线观看 | 91在线免费网站 | 久久久久久久久久一区二区 | 欧美精品久久久久久久多人混战 | 成人av在线网址 | 国产精品无码电影 | 一二三在线视频 | 久久av资源站 | 亚洲国产综合在线 | 韩国一区二区在线观看 | 精品免费看 | 日韩图色 | 国语对白永久免费 | 色综合久久久久久 | 91在线看片| 亚洲第七页 | 四虎国产成人永久精品免费 | 亚洲第一页av | 黄色91在线观看 | 亚洲综合欧美日韩 | 26uuu精品一区二区在线观看 | 欧美日韩一区二区在线播放 | 国产精品丝袜黑色高跟 | 美色视频 | 色乱码一区二区三在线看 | 国产尤物在线视频 | 欧美视频亚洲 | 精品久久久久一区二区国产 | 麻豆精品国产传媒 | 狠狠操狠狠插 | 国产精品久久久久不卡 | 抽插丰满内射高潮视频 | 伊人影院在线视频 | 性大毛片视频 | 亚洲另类av| 国产激情影院 | 国产成人精品一区在线播放 | 自拍偷拍另类 | 桃色一区| 欧美熟妇另类久久久久久不卡 | 亚洲 欧美 激情 小说 另类 | 天堂草在线观看 | 亚洲国产精品第一页 | 黄在线视频 | 搞逼综合网 | 少妇做爰xxxⅹ性视频 | 老司机精品在线 | 国产精品免费一区二区 | 爱爱免费视频 | 青青视频免费在线观看 |