国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

一文讀懂 JavaScript 中的 this 關鍵字

開發 前端
this 是一個令無數 JavaScript 編程者又愛又恨的知識點。它的重要性毋庸置疑,然而真正想掌握它卻并非易事。希望本文可以幫助大家理解 this。

this 是一個令無數 JavaScript 編程者又愛又恨的知識點。它的重要性毋庸置疑,然而真正想掌握它卻并非易事。希望本文可以幫助大家理解 this。

[[285731]]

JavaScript 中的 this

JavaScript 引擎在查找 this 時不會通過原型鏈一層一層的查找,因為 this 完全是在函數調用時才可以確定的,讓我們來看下面幾種函數調用的形式。

1. Function Invocation Pattern

普通的函數調用,這是我們使用較多的一種, foo 是以單獨的變量出現而不是屬性。其中的 this 指向全局對象。

  1. function foo() { 
  2.   console.log(this) 
  3.  
  4. foo() // Window 

函數作為對象的方法調用,會通過 obj.func 或者 obj[func] 的形式調用。其中的 this 指向調用它的對象。

  1. const obj = { 
  2.   name: 'lxfriday', 
  3.   getName(){ 
  4.     console.log(this.name) 
  5.   } 
  6.  
  7. obj.getName() // lxfriday 

2. Constructor Pattern

通過 new Constructor() 的形式調用,其 this 會指向新生成的對象。

  1. function Person(name){ 
  2.   this.name = name 
  3.  
  4. const person = new Person('lxfriday') 
  5. console.log(person.name) // lxfriday 

3. Apply Pattern

通過 foo.apply(thisObj) 或者 foo.call(thisObj) 的形式調用,其中的 this 指向 thisObj。如果 thisObj 是 null 或者 undefined ,其中的 this 會指向全局上下文 Window(在瀏覽器中)。

掌握以上的幾種函數調用形式就基本可以覆蓋開發中遇到的常見問題了,下面我翻譯了一篇文章,幫助你更深入的理解 this。

如果你已經使用過一些 JavaScript 庫,你一定會注意到一個特殊的關鍵字 this。

this 在 JavaScript 中很常見,但是有很多開發人員花了很多時間來完全理解 this 關鍵字的確切功能以及在代碼中何處使用。

在這篇文章中,我將幫助您深入了解 this 其機制。

在深入了解之前,請確保已在系統上安裝了 Node 。然后,打開命令終端并運行 node 命令。

全局環境中的 this

this 的工作機制并不容易理解。為了理解 this 是如何工作的,我們將探索不同環境中的 this。首先我們從全局上下文開始。

在全局層面中,this 等同于全局對象,在 Node repl(交互式命令行) 環境中叫 global。

  1. $ node 
  2. > this === global 
  3. true 

但上述情況只出現在 Node repl 環境中,如果我們在 JS 文件中跑相同的代碼,我們將會得到不同的答案。

為了測試,我們創建一個 index.js 的文件,并添加下面的代碼:

  1. console.log(this === global); 

然后通過 node 命令運行:

  1. $ node index.js 
  2. false  

出現上面情況的原因是在 JS 文件中, this 指向 module.exports,并不是指向 global。

函數中的 this

Function Invocation Pattern

在函數中 this 的指向取決于函數的調用形式。所以,函數每次執行的時候,可能擁有不同的 this 指向。

在 index.js 文件中,編寫一個非常簡單的函數來檢查 this 是否指向全局對象:

  1. function fat() { 
  2.   console.log(this === global) 
  3. fat() 

如果我們在 Node repl 環境執行上面的代碼,將會得到 true,但是如果添加 use strict 到首行,將會得到 false,因為這個時候 this 的值為 undefined。

為了進一步說明這一點,讓我們創建一個定義超級英雄的真實姓名和英雄姓名的簡單函數。

  1. function Hero(heroName, realName) { 
  2.   this.realName = realName; 
  3.   this.heroName = heroName; 
  4. const supermanHero("Superman", "Clark Kent"); 
  5. console.log(superman); 

請注意,這個函數不是在嚴格模式下執行的。代碼在 node 中運行將不會出現我們預期的 Superman 和 Clark Kent ,我們將得到 undefined。

這背后的原因是由于該函數不是以嚴格模式編寫的,所以 this 引用了全局對象。

如果我們在嚴格模式下運行這段代碼,會因為 JavaScript 不允許給 undefined 增加屬性而出現錯誤。這實際上是一件好事,因為它阻止我們創建全局變量。

最后,以大寫形式編寫函數的名稱意味著我們需要使用 new 運算符將其作為構造函數來調用。將上面的代碼片段的最后兩行替換為:

  1. const superman = new Hero("Superman", "Clark Kent"); 
  2. console.log(superman); 

再次運行 node index.js 命令,您現在將獲得預期的輸出。

構造函數中的 this

Constructor Pattern

JavaScript 沒有任何特殊的構造函數。我們所能做的就是使用 new 運算符將函數調用轉換為構造函數調用,如上一節所示。

進行構造函數調用時,將創建一個新對象并將其設置為函數的 this 參數。然后,從函數隱式返回該對象,除非我們有另一個要顯式返回的對象。

在 hero 函數內部編寫以下 return 語句:

  1. return { 
  2.   heroName: "Batman", 
  3.   realName: "Bruce Wayne", 
  4. }; 

如果現在運行 node 命令,我們將看到 return 語句將覆蓋構造函數調用。

當 return 語句嘗試返回不是對象的任何東西時,將隱式返回 this。

方法中的 this

Method Invocation Pattern

當將函數作為對象的方法調用時,this 指向該對象,然后將該對象稱為該函數調用的接收者。

在下面代碼中,有一個 dialogue 方法在 hero 對象內。通過 hero.dialogue() 形式調用時,dialogue 中的 this 就會指向 hero 本身。這里,hero 就是 dialogue 方法調用的接收者。

  1. const hero = { 
  2.   heroName: "Batman", 
  3.   dialogue() { 
  4.     console.log(`I am ${this.heroName}!`); 
  5.   } 
  6. }; 
  7. hero.dialogue(); 

上面的代碼非常簡單,但是實際開發時有可能方法調用的接收者并不是原對象。看下面的代碼:

  1. const saying = hero.dialogue(); 
  2. saying(); 

這里,我們把方法賦值給一個變量,然后執行這個變量指向的函數,你會發現 this 的值是 undefined。這是因為 dialogue 方法已經無法跟蹤原來的接收者對象,函數現在指向的是全局對象。

當我們將一個方法作為回調傳遞給另一個方法時,通常會發生接收器的丟失。我們可以通過添加包裝函數或使用 bind 方法將 this 綁定到特定對象來解決此問題。

call、apply

Apply Pattern

盡管函數的 this 值是隱式設置的,但我們也可以通過 call()和 apply() 顯式地綁定 this。

讓我們像這樣重組前面的代碼片段:

  1. function dialogue () { 
  2.   console.log (`I am ${this.heroName}`); 
  3. const hero = { 
  4.   heroName: 'Batman', 
  5. }; 

我們需要將hero 對象作為接收器與 dialogue 函數連接。為此,我們可以使用 call() 或 apply() 來實現連接:

  1. dialogue.call(hero) 
  2. // or 
  3. dialogue.apply(hero) 

需要注意的是,在非嚴格模式下,如果傳遞 null 或者 undefined 給 call 、 apply 作為上下文,將會導致 this 指向全局對象。

  1. function dialogue() { 
  2.   console.log('this', this) 
  3. const hero = { 
  4.   heroName: 'Batman', 
  5. console.log(dialogue.call(null)) 

上述代碼,在嚴格模式下輸出 null,非嚴格模式下輸出全局對象。

bind

當我們將一個方法作為回調傳遞給另一個函數時,始終存在丟失該方法的預期接收者的風險,導致將 this 參數設置為全局對象。

bind() 方法允許我們將 this 參數永久綁定到函數。因此,在下面的代碼片段中,bind 將創建一個新 dialogue 函數并將其 this 值設置為 hero。

  1. const hero = { 
  2.   heroName: "Batman", 
  3.   dialogue() { 
  4.     console.log(`I am ${this.heroName}`); 
  5.   } 
  6. }; 
  7. // 1s 后打印:I am Batman 
  8. setTimeout(hero.dialogue.bind(hero), 1000); 

注意:對于用 bind 綁定 this 之后新生成的函數,使用 call 或者 apply 方法無法更改這個新函數的 this。

箭頭函數中的 this

箭頭函數和普通函數有很大的不同,引用阮一峰 ES6入門第六章中的介紹:

  • 函數體內的 this 對象,就是定義時所在的對象,而不是使用時所在的對象;
  • 不可以當作構造函數,也就是說,不可以使用 new 命令,否則會拋出一個錯誤;
  • 不可以使用 arguments 對象,該對象在函數體內不存在。如果要用,可以用 rest 參數代替;
  • 不可以使用 yield 命令,因此箭頭函數不能用作 Generator 函數;

上面四點中,第一點尤其值得注意。this 對象的指向是可變的,但是在箭頭函數中,它是固定的,它只指向箭頭函數定義時的外層 this,箭頭函數沒有自己的 this,所有綁定 this 的操作,如 call apply bind 等,對箭頭函數中的 this 綁定都是無效的。

讓們看下面的代碼:

  1. const batman = this
  2. const bruce = () => { 
  3.   console.log(this === batman); 
  4. }; 
  5. bruce(); 

在這里,我們將 this 的值存儲在變量中,然后將該值與箭頭函數內部的 this 值進行比較。node index.js 執行時將會輸出 true。

那箭頭函數中的 this 可以做哪些事情呢?

箭頭函數可以幫助我們在回調中訪問 this。看一下我在下面寫的 counter 對象:

  1. const counter = { 
  2.   count: 0, 
  3.   increase() { 
  4.     setInterval(function() { 
  5.       console.log(++this.count); 
  6.     }, 1000); 
  7.   } 
  8. counter.increase(); 

運行上面的代碼,會打印 NaN。這是因為 this.count 沒有指向 counter 對象。它實際上指向全局對象。

要使此計數器工作,可以用箭頭函數重寫,下面代碼將會正常運行:

  1. const counter = { 
  2.   count: 0, 
  3.   increase () { 
  4.     setInterval (() => { 
  5.       console.log (++this.count); 
  6.     }, 1000); 
  7.   }, 
  8. }; 
  9. counter.increase (); 

類中的 this

類是所有 JavaScript 應用程序中最重要的部分之一。讓我們看看類內部 this 的行為。

一個類通常包含一個 constructor,其中 this 將指向新創建的對象。

但是,在使用方法的情況下,如果該方法以普通函數的形式調用,則 this 也可以指向任何其他值。就像一個方法一樣,類也可能無法跟蹤接收者。

我們用類重寫上面的 Hero 函數。此類將包含構造函數和 dialogue() 方法。最后,我們創建此類的實例并調用該 dialogue 方法。

  1. class Hero { 
  2.   constructor(heroName) { 
  3.     this.heroName = heroName; 
  4.   } 
  5.   dialogue() { 
  6.     console.log(`I am ${this.heroName}`) 
  7.   } 
  8. const batman = new Hero("Batman"); 
  9. batman.dialogue(); 

constructor 中的 this 指向新創建的類實例。batman.dialogue() 調用時,我們將 dialogue() 作為 batman 接收器的方法調用。

但是,如果我們存儲對 dialogue() 方法的引用,然后將其作為函數調用,則我們將再次失去方法的接收者,而 this 現在指向 undefined。

為什么是指向 undefined 呢?這是因為 JavaScript 類內部隱式以嚴格模式運行。我們將 say() 作為一個函數調用而沒有進行綁定。所以我們要手動的綁定。

  1. const say = batman.dialogue.bind(batman); 
  2. say(); 

當然,我們也可以在構造函數內部綁定:

  1. class Hero { 
  2.   constructor(heroName) { 
  3.     this.heroName = heroName 
  4.     thisthis.dialogue = this.dialogue.bind(this) 
  5.   } 
  6.   dialogue() { 
  7.     console.log(`I am ${this.heroName}`) 
  8.   } 

加餐:手寫 call、apply、bind

call 和 apply 的模擬實現大同小異,注意 apply 的參數是一個數組,綁定 this 都采用的是對象調用方法的形式。

  1. Function.prototype.call = function(thisObj) { 
  2.   thisObjthisObj = thisObj || window 
  3.   const funcName = Symbol('func') 
  4.   const that = this // func 
  5.   thisObj[funcName] = that 
  6.   const result = thisObj[funcName](...arguments) 
  7.   delete thisObj[funcName] 
  8.   return result 
  9.  
  10. Function.prototype.apply = function(thisObj) { 
  11.   thisObjthisObj = thisObj || window 
  12.   const funcName = Symbol('func') 
  13.   const that = this // func 
  14.   const args = arguments[1] || [] 
  15.   thisObj[funcName] = that 
  16.   const result = thisObj[funcName](...[thisObj, ...args]) 
  17.   delete thisObj[funcName] 
  18.   return result 
  19.  
  20. Function.prototype.bind = function(thisObj) { 
  21.   thisObjthisObj = thisObj || window 
  22.   const that = this // func 
  23.   const outerArgs = [...arguments].slice(1) 
  24.   return function(...innerArgs) { 
  25.     return that.apply(thisObj, outerArgs.concat(innerArgs)) 
  26.   } 

 

責任編輯:趙寧寧 來源: 今日頭條
相關推薦

2024-02-23 19:11:13

C++編程開發

2024-08-09 12:44:45

JavaScript原型鏈鏈條

2023-12-22 19:59:15

2021-08-04 16:06:45

DataOps智領云

2017-03-07 15:13:28

Scala偏函數函數

2022-04-20 11:10:17

bias推薦系統debias

2021-09-04 19:04:14

配置LogbackJava

2023-11-27 17:35:48

ComponentWeb外層

2021-12-29 18:00:19

無損網絡網絡通信網絡

2022-07-26 00:00:03

語言模型人工智能

2022-07-05 06:30:54

云網絡網絡云原生

2025-10-14 09:01:20

2022-12-01 17:23:45

2022-10-20 08:01:23

2023-05-20 17:58:31

低代碼軟件

2022-09-22 09:00:46

CSS單位

2025-04-03 10:56:47

2022-11-06 21:14:02

數據驅動架構數據

2018-09-28 14:06:25

前端緩存后端

2020-06-23 08:41:47

JavaScript開發技術
點贊
收藏

51CTO技術棧公眾號

先锋影音在线资源站91| 久久精品福利| 久久久久久一二三区| 97欧美精品一区二区三区| 中文字幕高清在线观看| 国产91在线|亚洲| 91在线视频导航| 秋霞国产精品| 色婷婷av一区二区三区之一色屋| 男人添女人下部视频免费| 日本在线电影一区二区三区| 亚洲欧美一区二区精品久久久| 性欧美16一18| 99久久99久久精品国产片果冻| 精品国产一区二区三区久久久久久| 自拍偷拍亚洲图片| 欧美成人性福生活免费看| 日本a级黄色| www.久久久久久久久| 美女三级99| 成人无号精品一区二区三区| www国产精品视频| 污视频网站免费在线观看| 欧美性色视频在线| 成人网免费视频| 国产成人一级电影| 视频一区视频二区视频三区高| 久久免费精品视频在这里| 久久久人成影片一区二区三区| caoprom在线| 欧美精品xxxxbbbb| 亚在线播放中文视频| 中文字幕国产精品一区二区| 黄色一级片av| 蜜乳av一区二区| 国产精品制服诱惑| 成人av国产| 日本欧美中文字幕| 视频二区欧美| 中文亚洲视频在线| 国偷自产一区二区免费视频| 日韩视频一区二区三区在线播放| 成人动漫在线免费观看| 日韩欧美一区二区三区| 中文字字幕在线中文乱码电影| 亚洲欧美综合另类在线卡通| 992kp快乐看片永久免费网址| 国产高清精品网站| 视色,视色影院,视色影库,视色网| 亚洲一区图片| 欧美精品国产精品久久久 | 国产精品嫩草影院com| 日本香蕉视频在线观看| 免费视频最近日韩| 亚洲精品国产精品国自产观看| 欧美亚洲一区| 欧美一区国产一区| 日本不卡的三区四区五区| 日韩电影在线播放| 久久国产精品色婷婷| 日韩极品视频在线观看| av高清久久久| 久久久久久久久久久久91| 国产精品久久久久永久免费观看| 丝袜制服影音先锋| 亚洲成人你懂的| 成人在线观看网站| 日韩精品一区二区三区四区视频| 男人天堂视频在线观看| 丝袜亚洲另类欧美重口| 久久精品国产亚洲blacked| 国产日韩欧美另类| 亚洲视频成人| 国产91porn| 国产精品三级电影| 在线看三级网站视频| 欧洲一区二区三区免费视频| 国产写真视频在线观看| 精品久久一区二区三区| 亚洲日韩中文字幕一区| 日产日韩在线亚洲欧美| 欧美日韩18| 日本久久高清视频| 国产精品五月天| 免费在线视频一级不卡| 亚洲国产成人91精品| 久久久国产精品入口麻豆| 91在线精品播放| 国产精品系列在线播放| 成视频免费在线看| 日韩精品综合一本久道在线视频| 成人在线网站| 97不卡在线视频| 最新成人av网站| 欧美大黑帍在线播放| 亚洲一二三四久久| 丁香花在线高清完整版视频| 久久色在线播放| 中文精品电影| www精品久久| 亚洲成人一区在线| 亚洲欧美一区二区三区| 欧美中文字幕视频| 蜜臀va亚洲va欧美va天堂| 一本色道久久亚洲综合精品蜜桃| 欧美又粗又大又爽| 日韩精品中文字幕一区二区| 精品国产乱码久久久久久郑州公司 | 97dyy97影院理论片在线| 欧美日韩一级片在线观看| 成人综合网站| 亚洲自拍偷拍视频| 久久久噜噜噜久久人人看| 福利在线播放| 欧美成人免费视频| 日本vs亚洲vs韩国一区三区二区 | 在线播放中文一区| 91久久精品无嫩草影院| 欧美精品一区在线发布| 中文字幕亚洲电影| 咪咪网在线视频| 成人www视频在线观看| 99精品国产热久久91蜜凸| 天堂地址在线www| 日韩美女激情视频| 国产福利精品导航| 天天综合视频在线观看| 欧美综合国产精品久久丁香| 国产成人福利片| 成人日韩欧美| 成人精品视频久久久久| 国产清纯白嫩初高生在线观看91| 日本一本在线免费福利| 亚洲伊人一本大道中文字幕| 国产精品免费久久| 欧美视频免费看| 色婷婷精品国产一区二区三区| 天天做天天摸天天爽国产一区| 99精品在免费线中文字幕网站一区 | 久久香蕉视频网站| 亚洲图片你懂的| 日韩精品专区| 性刺激综合网| 欧美美女一区二区在线观看| 久久中文字幕二区| 超清福利视频| 久久99青青精品免费观看| 国产福利视频一区二区三区| 色呦呦网站在线观看| 激情五月综合色婷婷一区二区 | 四虎永久在线高清国产精品| 中国人与牲禽动交精品| 日韩黄色免费网站| 激情视频在线观看| 国产精品久久一区二区三区| 婷婷亚洲久悠悠色悠在线播放| 西瓜成人精品人成网站| 中文字幕第100页| 精品中文字幕乱| 久久先锋影音av鲁色资源网| 欧美美女福利视频| 99视频在线免费播放| 亚洲网站在线播放| 国产精选一区二区三区| 精品91久久| 精品久久久久久无码中文野结衣| 日韩电影中文字幕一区| 国产精品一区在线观看你懂的| 婷婷综合六月| 大j8黑人w巨大888a片| 欧美成人午夜免费视在线看片 | 亚洲不卡中文字幕无码| 伊人久久久久久久久久久| 国产成人免费视频一区| 久久麻豆视频| 成人午夜视频免费在线观看| 久久久久免费精品国产| 亚洲青青青在线视频| 97精品国产福利一区二区三区| 日韩av资源站| 鲁丝片一区二区三区| 亚洲国产欧美一区二区三区久久| 九九视频精品免费| 国产成人久久精品麻豆二区| 丰满少妇在线观看| 青青久久aⅴ北条麻妃| 图片区小说区国产精品视频| 欧美福利一区| 激情av在线播放| 黄色免费视频大全| 日韩av123| 欧美日韩一本到| 蜜乳av一区二区三区| 成人亚洲免费| 久久.com| 久久99精品国产一区二区三区| 亚洲精选一区二区| 欧美激情一区二区三区蜜桃视频 | 欧美高清videos高潮hd| 六月婷婷久久|