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

JavaScript 中 this 的錯誤認識、綁定規則、常見問題講解

開發 前端
相信Javascript中的this會使很多同學在工作學習中產生困惑,筆者經過閱讀各種資料及實際工作中的應用,做了以下梳理,主要內容包括長期以來大家對this的錯誤認識及this的綁定規則,箭頭函數、實際工作場景中遇到的問題。

相信 Javascript 中的 this 會使很多同學在工作學習中產生困惑,筆者也同樣是,經過閱讀各種資料及實際工作中的應用,做了以下梳理,主要內容包括長期以來大家對 this 的錯誤認識及 this 的綁定規則,箭頭函數、實際工作場景中遇到的問題,希望對于有此困惑的你能有所幫助。

[[336197]]

一、兩種錯誤認識

1. 指向自身

this 的第一個錯誤認識是,很容易把 this 理解成指向函數自身,其實 this 的指向在函數定義階段是無法確定的,只有函數執行時才能確定 this 到底指向誰,實際 this 的最終指向是調用它的那個對象。

下面示例,聲明函數 foo(),執行 foo.count=0 時,像函數對象 foo 添加一個屬性 count。但是函數 foo 內部代碼 this.count 中的 this 并不是指向那個函數對象,for 循環中的 foo(i) 掉用它的對象是 window,等價于 window.foo(i),因此函數 foo 里面的 this 指向的是 window。

  1. function foo(num){ 
  2.   this.count++; // 記錄 foo 被調用次數 
  3. foo.count = 0
  4. window.count = 0
  5. for(let i=0; i<10; i++){ 
  6.   if(i > 5){ 
  7.     foo(i); 
  8.   } 
  9. console.log(foo.count, window.count); // 0 4 

2. 指向函數的作用域

對 this 的第二種誤解就是 this 指向函數的作用域

以下這段代碼,在 foo 中試圖調用 bar 函數,是否成功調用,取決于環境。

  • 瀏覽器:在瀏覽器環境里是沒有問題的,全局聲明的函數放在了 window 對象下,foo 函數里面的 this 代指的是 window 對象,在全局環境中并沒有聲明變量 a,因此在 bar 函數中的 this.a 自然沒有定義,輸出 undefined。
  • Node.js:在 Node.js 環境下,聲明的 function 不會放在 global 全局對象下,因此在 foo 函數里調用 this.bar 函數會報 TypeError: this.bar is not a function 錯誤。要想運行不報錯,調用 bar 函數時省去前面的 this。
  1. function foo(){ 
  2.   var a = 2
  3.   this.bar(); 
  4. function bar(){ 
  5.   console.log(this.a); 
  6. foo(); 

二、This 四種綁定規則

1. 默認綁定

當函數調用屬于獨立調用(不帶函數引用的調用),無法調用其他的綁定規則,我們給它一個稱呼 “默認綁定”,在非嚴格模式下綁定到全局對象,在使用了嚴格模式 (use strict) 下綁定到 undefined。

嚴格模式下調用:

  1. 'use strict' 
  2. function demo(){ 
  3.   // TypeError: Cannot read property 'a' of undefined 
  4.   console.log(this.a); 
  5. const a = 1
  6. demo(); 

非嚴格模式下調用:

在瀏覽器環境下會將 a 綁定到 window.a,以下代碼使用 var 聲明的變量 a 會輸出 1。

  1. function demo(){ 
  2.   console.log(this.a); // 1 
  3. var a = 1
  4. demo(); 

以下代碼使用 let 或 const 聲明變量 a 結果會輸出 undefined

  1. function demo(){ 
  2.   console.log(this.a); // undefined 
  3. let a = 1
  4. demo(); 

在舉例子的時候其實想要重點說明 this 的默認綁定關系的,但是你會發現上面兩種代碼因為分別使用了 var、let 進行聲明導致的結果也是不一樣的,歸其原因涉及到 頂層對象的概念

在 Issue: Nodejs-Roadmap/issues/11 里有童鞋提到這個疑問,也是之前的疏忽,再簡單聊下頂層對象的概念,頂層對象(瀏覽器環境指 window、Node.js 環境指 Global)的屬性和全局變量屬性的賦值是相等價的,使用 var 和 function 聲明的是頂層對象的屬性,而 let 就屬于 ES6 規范了,但是 ES6 規范中 let、const、class 這些聲明的全局變量,不再屬于頂層對象的屬性。

2. 隱式綁定

在函數的調用位置處被某個對象包含,擁有上下文,看以下示例:

  1. function child() { 
  2.   console.log(this.name); 
  3. let parent = { 
  4.   name: 'zhangsan', 
  5.   child, 
  6. parent.child(); // zhangsan 

函數在調用時會使用 parent 對象上下文來引用函數 child,可以理解為child 函數被調用時 parent 對象擁有或包含它。

隱式綁定的隱患:

被隱式綁定的函數,因為一些不小心的操作會丟失綁定對象,此時就會應用最開始講的綁定規則中的默認綁定,看下面代碼:

  1. function child() { 
  2.   console.log(this.name); 
  3. let parent = { 
  4.   name: 'zhangsan', 
  5.   child, 
  6. let parentparent2 = parent.child; 
  7. var name = 'lisi'
  8. parent2(); 

將 parent.child 函數本身賦給 parent2,調用 parent2() 其實是一個不帶任何修飾的函數調用,因此會應用默認綁定。

3. 顯示綁定

顯示綁定和隱式綁定從字面意思理解,有一個相反的對比,一個表現的更直接,一個表現的更委婉,下面在看下兩個規則各自的含義:

  • 隱式綁定:在一個對象的內部通過屬性間接引用函數,從而把 this 隱式綁定到對象內部屬性所指向的函數(例如上例中的對象 parent 的 child 屬性引用函數 function child(){})。
  • 顯示綁定:需要引用一個對象時進行強制綁定調用,js 有提供 call()、apply() 方法,ES5 中也提供了內置的方法 Function.prototype.bind。

call()、apply() 這兩個函數的第一個參數都是設置 this 對象,區別是 apply 傳遞參數是按照數組傳遞,call 是一個一個傳遞。

  1. function fruit(...args){ 
  2.   console.log(this.name, args); 
  3. var apple = { 
  4.   name: '蘋果' 
  5. var banana = { 
  6.   name: '香蕉' 
  7. fruit.call(banana, 'a', 'b')  // [ 'a', 'b' ] 
  8. fruit.apply(apple, ['a', 'b']) // [ 'a', 'b' ] 

下面是 bind 綁定的示例,只是將一個值綁定到函數的 this 上,并將綁定好的函數返回,只有在執行 fruit 函數時才會輸出信息,例:

  1. function fruit(){ 
  2.   console.log(this.name); 
  3. var apple = { 
  4.   name: '蘋果' 
  5. fruitfruit = fruit.bind(apple); 
  6. fruit(); // 蘋果 

除了以上 call、apply、bind 還可以通過上下文 context,例:

  1. function fruit(name){ 
  2.   console.log(`${this.name}: ${name}`); 
  3. const obj = { 
  4.   name: '這是水果', 
  5. const arr = ['蘋果', '香蕉']; 
  6. arr.forEach(fruit, obj); 
  7. // 這是水果: 蘋果 
  8. // 這是水果: 香蕉 

4. new 綁定

new 綁定也可以影響 this 調用,它是一個構造函數,每一次 new 綁定都會創建一個新對象。

  1. function Fruit(name){ 
  2.   this.name = name; 
  3.  
  4. const f1 = new Fruit('apple'); 
  5. const f2 = new Fruit('banana'); 
  6. console.log(f1.name, f2.name); // apple banana 

三、優先級

如果 this 的調用位置同時應用了多種綁定規則,它是有優先級的:new 綁定 -> 顯示綁定 -> 隱式綁定 -> 默認綁定。

四、箭頭函數

箭頭函數并非使用 function 關鍵字進行定義,也不會使用上面所講解的 this 四種標準規范,箭頭函數會繼承自外層函數調用的 this 綁定。

執行 fruit.call(apple) 時,箭頭函數 this 已被綁定,無法再次被修改。

  1. function fruit(){ 
  2.   return () => { 
  3.     console.log(this.name); 
  4.   } 
  5. var apple = { 
  6.   name: '蘋果' 
  7. var banana = { 
  8.   name: '香蕉' 
  9. var fruitfruitCall = fruit.call(apple); 
  10. fruitCall.call(banana); // 蘋果 

五、This 使用中的幾個常見問題

1. 通過函數和原型鏈模擬類

以下示例,定義函數 Fruit,之后在原型鏈上定義 info 方法,實例化對象 f1 和定義對象 f2 分別調用 info 方法。

  1. function Fruit(name) { 
  2.   this.name = name; 
  3. Fruit.prototype.info = function() { 
  4.   console.log(this.name); 
  5. const f1 = new Fruit('Apple'); 
  6. f1.info(); 
  7. const f2 = { name: 'Banana' }; 
  8. f2.info = f1.info; 
  9. f2.info() 

輸出之后,兩次結果是不一樣的,原因是 info 方法里的 this 對應的不是定義時的上下文,而是調用時的上下文,根據我們上面講的幾種綁定規則,對應的是隱式綁定規則。

  1. Apple 
  2. Banana 

2. 原型鏈上使用箭頭函數

如果使用構造函數和原型鏈模擬類,不能在原型鏈上定義箭頭函數,因為箭頭函數的里的 this 會繼承外層函數調用的 this 綁定。

  1. function Fruit(name) { 
  2.   this.name = name; 
  3. Fruit.prototype.info = () => { 
  4.   console.log(this.name); 
  5. var name = 'Banana' 
  6. const f1 = new Fruit('Apple'); 
  7. f1.info(); 

3. 在事件中的使用

舉一個 Node.js 示例,在事件中使用時,當我們的監聽器被調用時,如果聲明的是普通函數,this 會被指向監聽器所綁定的 EventEmitter 實例,如果使用的箭頭函數方式 this 不會指向 EventEmitter 實例。

  1. const EventEmitter = require('events'); 
  2. class MyEmitter extends EventEmitter { 
  3.   constructor() { 
  4.     super(); 
  5.     this.name = 'myEmitter'
  6.   } 
  7. const func1 = () => console.log(this.name); 
  8. const func2 = function () { console.log(this.name); }; 
  9. const myEmitter = new MyEmitter(); 
  10. myEmitter.on('event', func1); // undefined 
  11. myEmitter.on('event', func2); // myEmitter 
  12. myEmitter.emit('event'); 

 

責任編輯:趙寧寧 來源: Nodejs技術棧
相關推薦

2020-02-19 14:02:49

JavaScriptthis前端

2010-01-15 10:26:08

2019-10-30 14:58:45

MVCAndroid表現層

2013-04-07 10:17:54

WindowsPhon

2011-07-04 08:51:27

編程

2015-06-11 10:33:58

企業級云計算混合云應用

2022-07-31 23:54:24

Linux操作系統

2024-07-01 08:23:20

2011-07-14 14:15:40

ThreadLocal

2009-09-07 16:44:28

Linq String

2011-02-22 14:00:16

vsftpd

2015-12-21 11:45:27

C語言常見問題錯誤

2019-10-10 15:57:09

云安全混合云架構

2011-04-01 13:55:24

Java

2013-11-14 15:47:29

SDN問題答疑

2011-05-06 15:39:55

硒鼓

2010-07-21 09:10:02

Perl常見問題

2010-09-07 15:58:24

DB2數據庫性能

2010-09-27 13:45:38

2011-07-21 11:19:51

JAVA
點贊
收藏

51CTO技術棧公眾號

久久精品国产精品亚洲精品| 欧日韩精品视频| 亚洲自拍偷拍视频| 欧美高清免费| 欧美日韩情趣电影| 啦啦啦啦免费高清视频在线观看1| 久久亚洲二区三区| 人妻无码久久一区二区三区免费| 日韩国产精品久久| 国产一区二区高清视频| 国产精品久久久久久久久妇女| 久久久久国产精品免费网站| 日韩第二十一页| 亚洲视频网站在线观看| 成人一级福利| 日韩精品在线一区| 日韩免费啪啪| 欧美日韩一区二区三区视频| 国产精品99999| 在线视频欧美精品| 国产青青草在线| 欧美亚洲图片小说| 在线免费av网站| 欧美精品一卡二卡| www久久日com| 亚洲成人中文字幕| 中文字幕在线直播| 中文字幕精品网| 国产欧美自拍| 欧美日韩国产成人高清视频| 懂色av一区二区| 日韩av不卡在线| 久久国产亚洲| 国产欧美一区二区视频 | 欧美人妇做爰xxxⅹ性高电影| 成人精品一区二区三区免费 | 亚洲网友自拍| 欧美女孩性生活视频| av2020不卡| 在线亚洲国产精品网| 亚洲成人偷拍| 国产欧美久久一区二区| 一区二区激情| 一区二区三区四区欧美日韩| 不卡的av网站| 超清福利视频| 欧美性感一区二区三区| 日韩电影毛片| 性欧美视频videos6一9| 欧美在线免费| 在线国产精品网| 国产精品福利影院| 四虎影视在线播放| 亚洲激情在线视频| 综合视频一区| 国产在线精品一区| 99精品视频免费在线观看| jizzjizz中文| 欧美一区二区播放| 精品三级国产| 国产精品免费一区二区三区| 国产成人精品一区二| 国产毛片视频| 91精品在线免费观看| 国产日韩中文在线中文字幕| 99在线看视频| 99久久精品免费观看| 欧美日本网站| 中文字幕无线精品亚洲乱码一区 | 精品国内二区三区| 在线观看欧美| 国产不卡一区二区三区在线观看| 国产suv精品一区二区三区| 1024欧美极品| 亚洲黄色www| 欧美日韩国产一区二区三区不卡 | 亚洲私人影院| 国产成人精品视频免费看| 亚洲国产精品综合小说图片区| 999福利在线视频| 欧美自拍视频在线| 精品中文字幕一区二区小辣椒| 中文字幕校园春色| 一本大道久久加勒比香蕉| 综合一区av| 99热免费在线| 亚洲人成电影在线| 日韩天堂av| 91在线九色porny| 中文字幕成人在线| 亚洲欧美日韩专区| 成年人黄视频网站| 有码中文亚洲精品| 天堂成人免费av电影一区| 免费免费啪视频在线观看| 亚洲三级 欧美三级| 最新亚洲激情| 在线黄色国产电影| 欧美肥婆姓交大片| 麻豆精品国产传媒mv男同| 在线播放网站| 韩国欧美亚洲国产| 成人美女视频在线观看18| av网址在线免费观看| 91人人爽人人爽人人精88v| 国产精品成人在线观看| 97久久中文字幕| 日韩一二区视频| 精品少妇一区二区三区免费观看 | 久久综合伊人| 欧美一区二区少妇| 欧美一区二粉嫩精品国产一线天| 成人国产亚洲欧美成人综合网| 麻豆传媒视频在线观看| 国产精品久久久久不卡| 国产精品国产三级国产普通话蜜臀| 成人国产精品入口免费视频| 一区不卡字幕| 亚洲黄色在线观看| 日本欧美加勒比视频| 国产日产一区二区| 97人人干人人| 午夜国产精品一区| 国产一区二区欧美| 国产毛片视频| 国产91亚洲精品| 亚洲美女区一区| 狠狠做深爱婷婷综合一区| 好男人社区在线视频 | 久久av网站| 欧美日韩成人免费视频| 最近2019年好看中文字幕视频 | 一区二区欧美在线观看| 米奇精品关键词| 91插插插插插插插插| 欧美国产精品日韩| 国产精品污www在线观看| 欧美变态网站| 激情视频网址| 成人久久一区二区| 欧美亚洲免费在线一区| 国产一区二区三区的电影| 丝袜在线视频| 日本在线视频www色| 亚洲美女动态图120秒| 国产在线精品一区二区不卡了| 国产超碰精品| 无码aⅴ精品一区二区三区浪潮| 欧美日韩福利在线观看| 亚洲欧美另类久久久精品| 国产二区精品| 免费在线观看的电影网站| 国产精品igao激情视频| 日韩一二三在线视频播| 国产日韩欧美精品在线| 在线看成人短视频| 高清国产福利在线观看| 亚洲一区二区三区精品动漫| 久久精品国产2020观看福利| 亚洲欧洲另类国产综合| 欧美精品综合| 北岛玲heyzo一区二区| 少妇黄色一级片| 91成人伦理在线电影| 亚洲国产精品成人va在线观看| 91在线精品一区二区| 精品视频免费在线观看| 国产麻豆精品theporn| 视频一区中文| 在线观看完整版免费| 日韩精品一区二区三区四| 另类尿喷潮videofree| 国产二区三区四区| 91久久在线观看| 日韩一区二区在线看片| 国产成人av电影在线| 精品网站aaa| 国产无套粉嫩白浆在线2022年 | 久久综合毛片| 中文字幕久精品免费视频| 一区二区三区欧美久久| 免费在线亚洲| 国产精品日本一区二区不卡视频 | 超碰国产在线| 国产av熟女一区二区三区 | 一区二区三区不卡在线观看| 亚洲美女一区| 韩国一区二区三区视频| 欧美69xxxxx| 可以看毛片的网址| 亚洲一区二区三区乱码aⅴ蜜桃女| 日韩电影网在线| 一区二区三区国产精品| 九九国产精品视频| 国产一区二区欧美| 精品成人av| 91激情在线| 四虎精品一区二区永久在线观看| 日韩精品一区二区三区外面| 国产成人精品电影久久久|